@umituz/react-native-ai-generation-content 1.17.185 → 1.17.187

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.185",
3
+ "version": "1.17.187",
4
4
  "description": "Provider-agnostic AI generation orchestration for React Native",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -23,7 +23,7 @@ export interface UseCreationPersistenceConfig {
23
23
  /** Credit cost for this feature (passed to onCreditDeduct) */
24
24
  readonly creditCost?: number;
25
25
  /** Callback to deduct credits on successful processing */
26
- readonly onCreditDeduct?: (cost: number) => Promise<void>;
26
+ readonly onCreditDeduct?: (cost: number) => Promise<void | boolean>;
27
27
  }
28
28
 
29
29
  /**
package/src/index.ts CHANGED
@@ -150,3 +150,30 @@ export * from "./features/text-to-voice";
150
150
  export * from "./features/hd-touch-up";
151
151
  export * from "./features/meme-generator";
152
152
  export * from "./infrastructure/orchestration";
153
+
154
+ // Unified AI Feature Screen
155
+ export {
156
+ AIFeatureScreen,
157
+ AI_FEATURE_CONFIGS,
158
+ getAIFeatureConfig,
159
+ hasAIFeature,
160
+ getAllAIFeatureIds,
161
+ getAIFeaturesByMode,
162
+ createFeatureTranslations,
163
+ createSingleImageTranslations,
164
+ createDualImageTranslations,
165
+ createComparisonTranslations,
166
+ createPromptTranslations,
167
+ } from "./presentation/screens/ai-feature";
168
+ export type {
169
+ AIFeatureId,
170
+ AIFeatureMode,
171
+ AIFeatureOutputType,
172
+ AIFeatureCreditType,
173
+ AIFeatureConfig,
174
+ AIFeatureScreenProps,
175
+ SingleImageTranslationKeys,
176
+ DualImageTranslationKeys,
177
+ ComparisonTranslationKeys,
178
+ PromptTranslationKeys,
179
+ } from "./presentation/screens/ai-feature";
@@ -0,0 +1,157 @@
1
+ /**
2
+ * AIFeatureScreen
3
+ * Unified screen component for all AI features
4
+ * Reduces 9 screens to 1 configurable component
5
+ */
6
+
7
+ import React, { useMemo, useCallback } from "react";
8
+ import { View } from "react-native";
9
+ import { ScreenLayout } from "@umituz/react-native-design-system";
10
+ import { useLocalization } from "@umituz/react-native-localization";
11
+
12
+ import { AIGenScreenHeader } from "../../components/headers/AIGenScreenHeader";
13
+ import { CreditBadge } from "../../components/headers/CreditBadge";
14
+ import { prepareImage } from "../../../infrastructure/utils/feature-utils";
15
+ import { useCreationPersistence } from "../../../domains/creations/presentation/hooks/useCreationPersistence";
16
+
17
+ // Feature components
18
+ import { AnimeSelfieFeature } from "../../../features/anime-selfie/presentation/components/AnimeSelfieFeature";
19
+ import { RemoveBackgroundFeature } from "../../../features/remove-background/presentation/components/RemoveBackgroundFeature";
20
+ import { HDTouchUpFeature } from "../../../features/hd-touch-up/presentation/components/HDTouchUpFeature";
21
+ import { UpscaleFeature } from "../../../features/upscaling/presentation/components/UpscaleFeature";
22
+ import { PhotoRestoreFeature } from "../../../features/photo-restoration/presentation/components/PhotoRestoreFeature";
23
+ import { RemoveObjectFeature } from "../../../features/remove-object/presentation/components/RemoveObjectFeature";
24
+ import { ReplaceBackgroundFeature } from "../../../features/replace-background/presentation/components/ReplaceBackgroundFeature";
25
+ import { FaceSwapFeature } from "../../../features/face-swap/presentation/components/FaceSwapFeature";
26
+ import { AIHugFeature } from "../../../features/ai-hug/presentation/components/AIHugFeature";
27
+ import { AIKissFeature } from "../../../features/ai-kiss/presentation/components/AIKissFeature";
28
+
29
+ import { createFeatureTranslations } from "./translations";
30
+ import type { AIFeatureScreenProps, AIFeatureId } from "./types";
31
+
32
+ /**
33
+ * Feature component mapping
34
+ * Using explicit any type for component registry to allow dynamic prop injection
35
+ */
36
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
37
+ const FEATURE_COMPONENTS: Record<AIFeatureId, React.ComponentType<any>> = {
38
+ "anime-selfie": AnimeSelfieFeature,
39
+ "remove-background": RemoveBackgroundFeature,
40
+ "hd-touch-up": HDTouchUpFeature,
41
+ upscale: UpscaleFeature,
42
+ "photo-restore": PhotoRestoreFeature,
43
+ "remove-object": RemoveObjectFeature,
44
+ "replace-background": ReplaceBackgroundFeature,
45
+ "face-swap": FaceSwapFeature,
46
+ "ai-hug": AIHugFeature,
47
+ "ai-kiss": AIKissFeature,
48
+ };
49
+
50
+ /**
51
+ * AIFeatureScreen - Unified component for all AI features
52
+ */
53
+ export const AIFeatureScreen: React.FC<AIFeatureScreenProps> = ({
54
+ config,
55
+ creditCost,
56
+ onDeductCredits,
57
+ onSelectImage,
58
+ onSaveMedia,
59
+ onCheckCreditGuard,
60
+ imageCredits,
61
+ headerRightContent,
62
+ }) => {
63
+ const { t } = useLocalization();
64
+
65
+ // Create persistence callbacks
66
+ const persistence = useCreationPersistence({
67
+ type: config.id,
68
+ creditCost,
69
+ onCreditDeduct: onDeductCredits,
70
+ });
71
+
72
+ // Create translations based on feature mode
73
+ const translations = useMemo(
74
+ () => createFeatureTranslations(config, t),
75
+ [config, t],
76
+ );
77
+
78
+ // Create feature config
79
+ const featureConfig = useMemo(
80
+ () => ({
81
+ prepareImage,
82
+ ...config.extraConfig,
83
+ ...persistence,
84
+ }),
85
+ [config.extraConfig, persistence],
86
+ );
87
+
88
+ // Credit guard callback
89
+ const handleBeforeProcess = useCallback(async () => {
90
+ // Convert featureId to PascalCase for analytics
91
+ const featureName = config.id
92
+ .split("-")
93
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
94
+ .join("");
95
+ return onCheckCreditGuard(creditCost, featureName);
96
+ }, [config.id, creditCost, onCheckCreditGuard]);
97
+
98
+ // Get the feature component
99
+ const FeatureComponent = FEATURE_COMPONENTS[config.id];
100
+
101
+ // Build props based on feature mode
102
+ const featureProps = useMemo(() => {
103
+ const baseProps = {
104
+ config: featureConfig,
105
+ translations,
106
+ onBeforeProcess: handleBeforeProcess,
107
+ };
108
+
109
+ // Add mode-specific props
110
+ switch (config.mode) {
111
+ case "single":
112
+ case "single-with-prompt":
113
+ return {
114
+ ...baseProps,
115
+ onSelectImage,
116
+ onSaveImage: onSaveMedia,
117
+ };
118
+ case "dual":
119
+ return {
120
+ ...baseProps,
121
+ onSelectSourceImage: onSelectImage,
122
+ onSelectTargetImage: onSelectImage,
123
+ onSaveImage: onSaveMedia,
124
+ };
125
+ case "dual-video":
126
+ return {
127
+ ...baseProps,
128
+ onSelectSourceImage: onSelectImage,
129
+ onSelectTargetImage: onSelectImage,
130
+ onSaveVideo: onSaveMedia,
131
+ };
132
+ default:
133
+ return baseProps;
134
+ }
135
+ }, [config.mode, featureConfig, translations, handleBeforeProcess, onSelectImage, onSaveMedia]);
136
+
137
+ // Default header right content with credit badge
138
+ const defaultHeaderRight = (
139
+ <View style={{ flexDirection: "row", alignItems: "center", gap: 8 }}>
140
+ <CreditBadge credits={imageCredits} compact />
141
+ </View>
142
+ );
143
+
144
+ return (
145
+ <ScreenLayout
146
+ header={
147
+ <AIGenScreenHeader
148
+ title={t(`${config.translationPrefix}.title`)}
149
+ rightContent={headerRightContent ?? defaultHeaderRight}
150
+ />
151
+ }
152
+ scrollable={false}
153
+ >
154
+ <FeatureComponent {...featureProps} />
155
+ </ScreenLayout>
156
+ );
157
+ };
@@ -0,0 +1,20 @@
1
+ /**
2
+ * AI Feature Screen
3
+ * Unified screen component for all AI features
4
+ */
5
+
6
+ export { AIFeatureScreen } from "./AIFeatureScreen";
7
+ export { AI_FEATURE_CONFIGS, getAIFeatureConfig, hasAIFeature, getAllAIFeatureIds, getAIFeaturesByMode } from "./registry";
8
+ export { createFeatureTranslations, createSingleImageTranslations, createDualImageTranslations, createComparisonTranslations, createPromptTranslations } from "./translations";
9
+ export type {
10
+ AIFeatureId,
11
+ AIFeatureMode,
12
+ AIFeatureOutputType,
13
+ AIFeatureCreditType,
14
+ AIFeatureConfig,
15
+ AIFeatureScreenProps,
16
+ SingleImageTranslationKeys,
17
+ DualImageTranslationKeys,
18
+ ComparisonTranslationKeys,
19
+ PromptTranslationKeys,
20
+ } from "./types";
@@ -0,0 +1,130 @@
1
+ /**
2
+ * AI Feature Registry
3
+ * Static configuration for all AI features
4
+ */
5
+
6
+ import type { AIFeatureConfig, AIFeatureId } from "./types";
7
+
8
+ /**
9
+ * Feature configurations registry
10
+ */
11
+ export const AI_FEATURE_CONFIGS: Record<AIFeatureId, AIFeatureConfig> = {
12
+ // Single image features
13
+ "anime-selfie": {
14
+ id: "anime-selfie",
15
+ mode: "single",
16
+ outputType: "image",
17
+ creditType: "image",
18
+ translationPrefix: "anime-selfie",
19
+ },
20
+ "remove-background": {
21
+ id: "remove-background",
22
+ mode: "single",
23
+ outputType: "image",
24
+ creditType: "image",
25
+ translationPrefix: "remove-background",
26
+ extraConfig: { featureType: "remove-background" },
27
+ },
28
+ "hd-touch-up": {
29
+ id: "hd-touch-up",
30
+ mode: "single",
31
+ outputType: "image",
32
+ creditType: "image",
33
+ translationPrefix: "hd-touch-up",
34
+ extraConfig: { featureType: "hd-touch-up" },
35
+ },
36
+
37
+ // Comparison result features
38
+ upscale: {
39
+ id: "upscale",
40
+ mode: "single",
41
+ outputType: "image",
42
+ creditType: "image",
43
+ translationPrefix: "upscale",
44
+ hasComparisonResult: true,
45
+ extraConfig: { featureType: "upscale", defaultScaleFactor: 2 },
46
+ },
47
+ "photo-restore": {
48
+ id: "photo-restore",
49
+ mode: "single",
50
+ outputType: "image",
51
+ creditType: "image",
52
+ translationPrefix: "photo-restore",
53
+ hasComparisonResult: true,
54
+ },
55
+
56
+ // Prompt features
57
+ "remove-object": {
58
+ id: "remove-object",
59
+ mode: "single-with-prompt",
60
+ outputType: "image",
61
+ creditType: "image",
62
+ translationPrefix: "remove-object",
63
+ },
64
+ "replace-background": {
65
+ id: "replace-background",
66
+ mode: "single-with-prompt",
67
+ outputType: "image",
68
+ creditType: "image",
69
+ translationPrefix: "replace-background",
70
+ extraConfig: { featureType: "replace-background" },
71
+ },
72
+
73
+ // Dual image features
74
+ "face-swap": {
75
+ id: "face-swap",
76
+ mode: "dual",
77
+ outputType: "image",
78
+ creditType: "image",
79
+ translationPrefix: "face-swap",
80
+ extraConfig: { featureType: "face-swap" },
81
+ },
82
+
83
+ // Dual image video features
84
+ "ai-hug": {
85
+ id: "ai-hug",
86
+ mode: "dual-video",
87
+ outputType: "video",
88
+ creditType: "image",
89
+ translationPrefix: "ai-hug",
90
+ },
91
+ "ai-kiss": {
92
+ id: "ai-kiss",
93
+ mode: "dual-video",
94
+ outputType: "video",
95
+ creditType: "image",
96
+ translationPrefix: "ai-kiss",
97
+ },
98
+ };
99
+
100
+ /**
101
+ * Get feature config by ID
102
+ */
103
+ export function getAIFeatureConfig(featureId: AIFeatureId): AIFeatureConfig {
104
+ const config = AI_FEATURE_CONFIGS[featureId];
105
+ if (!config) {
106
+ throw new Error(`Unknown AI feature: ${featureId}`);
107
+ }
108
+ return config;
109
+ }
110
+
111
+ /**
112
+ * Check if feature exists
113
+ */
114
+ export function hasAIFeature(featureId: string): featureId is AIFeatureId {
115
+ return featureId in AI_FEATURE_CONFIGS;
116
+ }
117
+
118
+ /**
119
+ * Get all feature IDs
120
+ */
121
+ export function getAllAIFeatureIds(): AIFeatureId[] {
122
+ return Object.keys(AI_FEATURE_CONFIGS) as AIFeatureId[];
123
+ }
124
+
125
+ /**
126
+ * Get features by mode
127
+ */
128
+ export function getAIFeaturesByMode(mode: AIFeatureConfig["mode"]): AIFeatureConfig[] {
129
+ return Object.values(AI_FEATURE_CONFIGS).filter((config) => config.mode === mode);
130
+ }
@@ -0,0 +1,94 @@
1
+ /**
2
+ * AI Feature Translations Factory
3
+ * Creates translation objects from prefix and t function
4
+ */
5
+
6
+ import type { AIFeatureConfig } from "./types";
7
+
8
+ type TranslateFunction = (key: string) => string;
9
+
10
+ /**
11
+ * Create single image translations
12
+ */
13
+ export function createSingleImageTranslations(prefix: string, t: TranslateFunction) {
14
+ return {
15
+ uploadTitle: t(`${prefix}.uploadTitle`),
16
+ uploadSubtitle: t(`${prefix}.uploadSubtitle`),
17
+ uploadChange: t(`${prefix}.uploadChange`),
18
+ uploadAnalyzing: t(`${prefix}.uploadAnalyzing`),
19
+ description: t(`${prefix}.description`),
20
+ processingText: t(`${prefix}.processingText`),
21
+ processButtonText: t(`${prefix}.processButtonText`),
22
+ successText: t(`${prefix}.successText`),
23
+ saveButtonText: t(`${prefix}.saveButtonText`),
24
+ tryAnotherText: t(`${prefix}.tryAnotherText`),
25
+ };
26
+ }
27
+
28
+ /**
29
+ * Create comparison result translations (upscale, photo-restore)
30
+ */
31
+ export function createComparisonTranslations(prefix: string, t: TranslateFunction) {
32
+ return {
33
+ ...createSingleImageTranslations(prefix, t),
34
+ beforeLabel: t(`${prefix}.beforeLabel`),
35
+ afterLabel: t(`${prefix}.afterLabel`),
36
+ };
37
+ }
38
+
39
+ /**
40
+ * Create prompt feature translations (remove-object, replace-background)
41
+ */
42
+ export function createPromptTranslations(prefix: string, t: TranslateFunction) {
43
+ return {
44
+ ...createSingleImageTranslations(prefix, t),
45
+ promptPlaceholder: t(`${prefix}.promptPlaceholder`),
46
+ maskTitle: t(`${prefix}.maskTitle`),
47
+ maskSubtitle: t(`${prefix}.maskSubtitle`),
48
+ };
49
+ }
50
+
51
+ /**
52
+ * Create dual image translations (face-swap, ai-hug, ai-kiss)
53
+ */
54
+ export function createDualImageTranslations(prefix: string, t: TranslateFunction) {
55
+ return {
56
+ sourceUploadTitle: t(`${prefix}.sourceUploadTitle`),
57
+ sourceUploadSubtitle: t(`${prefix}.sourceUploadSubtitle`),
58
+ targetUploadTitle: t(`${prefix}.targetUploadTitle`),
59
+ targetUploadSubtitle: t(`${prefix}.targetUploadSubtitle`),
60
+ uploadChange: t(`${prefix}.uploadChange`),
61
+ uploadAnalyzing: t(`${prefix}.uploadAnalyzing`),
62
+ description: t(`${prefix}.description`),
63
+ processingText: t(`${prefix}.processingText`),
64
+ processButtonText: t(`${prefix}.processButtonText`),
65
+ successText: t(`${prefix}.successText`),
66
+ saveButtonText: t(`${prefix}.saveButtonText`),
67
+ tryAnotherText: t(`${prefix}.tryAnotherText`),
68
+ modalTitle: t(`${prefix}.modalTitle`),
69
+ modalMessage: t(`${prefix}.modalMessage`),
70
+ modalHint: t(`${prefix}.modalHint`),
71
+ modalBackgroundHint: t(`${prefix}.modalBackgroundHint`),
72
+ };
73
+ }
74
+
75
+ /**
76
+ * Create translations based on feature config
77
+ */
78
+ export function createFeatureTranslations(config: AIFeatureConfig, t: TranslateFunction) {
79
+ const { translationPrefix, mode, hasComparisonResult } = config;
80
+
81
+ switch (mode) {
82
+ case "single":
83
+ return hasComparisonResult
84
+ ? createComparisonTranslations(translationPrefix, t)
85
+ : createSingleImageTranslations(translationPrefix, t);
86
+ case "single-with-prompt":
87
+ return createPromptTranslations(translationPrefix, t);
88
+ case "dual":
89
+ case "dual-video":
90
+ return createDualImageTranslations(translationPrefix, t);
91
+ default:
92
+ return createSingleImageTranslations(translationPrefix, t);
93
+ }
94
+ }
@@ -0,0 +1,141 @@
1
+ /**
2
+ * AIFeatureScreen Types
3
+ * Unified type definitions for all AI feature screens
4
+ */
5
+
6
+ import type { ReactNode } from "react";
7
+
8
+ /**
9
+ * All supported AI feature types
10
+ */
11
+ export type AIFeatureId =
12
+ | "anime-selfie"
13
+ | "remove-background"
14
+ | "hd-touch-up"
15
+ | "upscale"
16
+ | "photo-restore"
17
+ | "remove-object"
18
+ | "replace-background"
19
+ | "face-swap"
20
+ | "ai-hug"
21
+ | "ai-kiss";
22
+
23
+ /**
24
+ * Image mode for the feature
25
+ */
26
+ export type AIFeatureMode = "single" | "single-with-prompt" | "dual" | "dual-video";
27
+
28
+ /**
29
+ * Output type of the feature
30
+ */
31
+ export type AIFeatureOutputType = "image" | "video";
32
+
33
+ /**
34
+ * Credit type for the feature
35
+ */
36
+ export type AIFeatureCreditType = "image" | "video";
37
+
38
+ /**
39
+ * Translation keys structure for single image features
40
+ */
41
+ export interface SingleImageTranslationKeys {
42
+ uploadTitle: string;
43
+ uploadSubtitle: string;
44
+ uploadChange: string;
45
+ uploadAnalyzing: string;
46
+ description: string;
47
+ processingText: string;
48
+ processButtonText: string;
49
+ successText: string;
50
+ saveButtonText: string;
51
+ tryAnotherText: string;
52
+ }
53
+
54
+ /**
55
+ * Translation keys structure for comparison result features (upscale, photo-restore)
56
+ */
57
+ export interface ComparisonTranslationKeys extends SingleImageTranslationKeys {
58
+ beforeLabel: string;
59
+ afterLabel: string;
60
+ }
61
+
62
+ /**
63
+ * Translation keys structure for prompt features (remove-object, replace-background)
64
+ */
65
+ export interface PromptTranslationKeys extends SingleImageTranslationKeys {
66
+ promptPlaceholder: string;
67
+ maskTitle?: string;
68
+ maskSubtitle?: string;
69
+ }
70
+
71
+ /**
72
+ * Translation keys structure for dual image features
73
+ */
74
+ export interface DualImageTranslationKeys {
75
+ sourceUploadTitle: string;
76
+ sourceUploadSubtitle: string;
77
+ targetUploadTitle: string;
78
+ targetUploadSubtitle: string;
79
+ uploadChange: string;
80
+ uploadAnalyzing: string;
81
+ description: string;
82
+ processingText: string;
83
+ processButtonText: string;
84
+ successText: string;
85
+ saveButtonText: string;
86
+ tryAnotherText: string;
87
+ modalTitle?: string;
88
+ modalMessage?: string;
89
+ modalHint?: string;
90
+ modalBackgroundHint?: string;
91
+ }
92
+
93
+ /**
94
+ * Static feature configuration (doesn't change at runtime)
95
+ */
96
+ export interface AIFeatureConfig {
97
+ /** Unique feature identifier */
98
+ readonly id: AIFeatureId;
99
+ /** Feature mode: single image, dual image, etc. */
100
+ readonly mode: AIFeatureMode;
101
+ /** Output type: image or video */
102
+ readonly outputType: AIFeatureOutputType;
103
+ /** Credit type to deduct */
104
+ readonly creditType: AIFeatureCreditType;
105
+ /** Translation key prefix (e.g., "anime-selfie" for t("anime-selfie.uploadTitle")) */
106
+ readonly translationPrefix: string;
107
+ /** Whether this feature has comparison result (before/after slider) */
108
+ readonly hasComparisonResult?: boolean;
109
+ /** Feature-specific extra config */
110
+ readonly extraConfig?: Record<string, unknown>;
111
+ }
112
+
113
+ /**
114
+ * Runtime props for AIFeatureScreen
115
+ */
116
+ export interface AIFeatureScreenProps {
117
+ /** Feature configuration from registry */
118
+ readonly config: AIFeatureConfig;
119
+ /** Credit cost for this feature */
120
+ readonly creditCost: number;
121
+ /** Deduct credits callback */
122
+ readonly onDeductCredits: (cost: number) => Promise<void | boolean>;
123
+ /** Select image callback */
124
+ readonly onSelectImage: () => Promise<string | null>;
125
+ /** Save media callback */
126
+ readonly onSaveMedia: (url: string) => Promise<void>;
127
+ /** Credit guard check callback */
128
+ readonly onCheckCreditGuard: (cost: number, featureName: string) => Promise<boolean>;
129
+ /** Current image credits count */
130
+ readonly imageCredits: number;
131
+ /** Custom header right content */
132
+ readonly headerRightContent?: ReactNode;
133
+ }
134
+
135
+ /**
136
+ * Feature registry entry with component
137
+ */
138
+ export interface AIFeatureRegistryEntry extends AIFeatureConfig {
139
+ /** The Feature component to render */
140
+ readonly Component: React.ComponentType<unknown>;
141
+ }