@umituz/react-native-ai-generation-content 1.20.12 → 1.20.13
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/features/ai-hug/presentation/components/AIHugFeature.tsx +2 -14
- package/src/features/ai-kiss/presentation/components/AIKissFeature.tsx +2 -17
- package/src/features/anime-selfie/presentation/components/AnimeSelfieFeature.tsx +2 -19
- package/src/features/anime-selfie/presentation/hooks/useAnimeSelfieFeature.ts +1 -1
- package/src/features/face-swap/presentation/components/FaceSwapFeature.tsx +2 -18
- package/src/features/hd-touch-up/presentation/components/HDTouchUpFeature.tsx +2 -18
- package/src/features/image-to-image/presentation/hooks/useDualImageFeature.ts +1 -1
- package/src/features/image-to-image/presentation/hooks/useImageWithPromptFeature.ts +1 -1
- package/src/features/image-to-image/presentation/hooks/useSingleImageFeature.ts +2 -5
- package/src/features/photo-restoration/presentation/components/PhotoRestoreFeature.tsx +2 -18
- package/src/features/remove-background/presentation/components/RemoveBackgroundFeature.tsx +2 -14
- package/src/features/remove-object/presentation/components/RemoveObjectFeature.tsx +5 -26
- package/src/features/remove-object/presentation/hooks/useRemoveObjectFeature.ts +1 -1
- package/src/features/replace-background/presentation/components/ReplaceBackgroundFeature.tsx +2 -18
- package/src/features/shared/dual-image-video/presentation/hooks/useDualImageVideoFeature.ts +1 -1
- package/src/features/text-to-video/presentation/hooks/useTextToVideoFeature.ts +1 -1
- package/src/features/upscaling/presentation/components/UpscaleFeature.tsx +2 -18
- package/src/features/wizard/presentation/components/AIGenerationWizard.tsx +2 -6
- package/src/index.ts +10 -11
- package/src/presentation/components/AIGenerationForm.tsx +0 -16
- package/src/presentation/components/index.ts +0 -6
- package/src/presentation/layouts/DualImageFeatureLayout.tsx +65 -56
- package/src/presentation/layouts/DualImageVideoFeatureLayout.tsx +65 -56
- package/src/presentation/layouts/SingleImageFeatureLayout.tsx +63 -54
- package/src/presentation/layouts/SingleImageWithPromptFeatureLayout.tsx +65 -56
- package/src/presentation/layouts/index.ts +0 -7
- package/src/presentation/layouts/types/index.ts +1 -5
- package/src/presentation/layouts/types/layout-props.ts +13 -21
- package/src/presentation/layouts/types/result-props.ts +0 -8
- package/src/presentation/components/GenerationProgressModal.tsx +0 -134
package/src/index.ts
CHANGED
|
@@ -85,7 +85,7 @@ export type {
|
|
|
85
85
|
} from "./presentation/hooks";
|
|
86
86
|
|
|
87
87
|
export {
|
|
88
|
-
|
|
88
|
+
GenerationProgressContent, GenerationProgressBar, PendingJobCard,
|
|
89
89
|
PendingJobProgressBar, PendingJobCardActions, GenerationResultContent, ResultHeader,
|
|
90
90
|
ResultImageCard, ResultStoryCard, ResultActions, DEFAULT_RESULT_CONFIG, PhotoStep,
|
|
91
91
|
DualImagePicker, PromptInput, AIGenerationHero, ExamplePrompts, ModerationSummary,
|
|
@@ -105,20 +105,19 @@ export type {
|
|
|
105
105
|
SingleImageInputRenderProps, SingleImageWithPromptInputRenderProps,
|
|
106
106
|
SingleImageWithPromptFeatureState, SingleImageWithPromptFeatureLayoutProps,
|
|
107
107
|
DualImageInputRenderProps, ResultRenderProps, CustomResultRenderProps,
|
|
108
|
-
|
|
108
|
+
SingleImageFeatureLayoutProps, DualImageFeatureLayoutProps,
|
|
109
109
|
DualImageVideoFeatureState, DualImageVideoFeatureLayoutProps,
|
|
110
110
|
} from "./presentation/layouts";
|
|
111
111
|
|
|
112
112
|
export type {
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
FeatureHeaderProps, AIGenScreenHeaderProps, NavigationButtonType, CreditBadgeProps,
|
|
113
|
+
GenerationProgressContentProps, GenerationProgressBarProps, PendingJobCardProps, StatusLabels,
|
|
114
|
+
PendingJobProgressBarProps, PendingJobCardActionsProps, GenerationResultData, GenerationResultContentProps,
|
|
115
|
+
ResultHeaderProps, ResultImageCardProps, ResultStoryCardProps, ResultActionsProps, ResultConfig,
|
|
116
|
+
ResultHeaderConfig, ResultImageConfig, ResultStoryConfig, ResultActionsConfig, ResultLayoutConfig,
|
|
117
|
+
ResultActionButton, PhotoStepProps, DualImagePickerProps, PromptInputProps, AIGenerationHeroProps,
|
|
118
|
+
ExamplePromptsProps, ModerationSummaryProps, StylePresetsGridProps, StylePreset, GenerateButtonProps,
|
|
119
|
+
ResultDisplayProps, ResultDisplayAction, AIGenerationResultProps, AIGenerationResultAction,
|
|
120
|
+
ErrorDisplayProps, FeatureHeaderProps, AIGenScreenHeaderProps, NavigationButtonType, CreditBadgeProps,
|
|
122
121
|
PhotoUploadCardProps, PhotoUploadCardConfig, SettingsSheetProps, StyleSelectorProps,
|
|
123
122
|
AspectRatioSelectorProps, DurationSelectorProps, GridSelectorProps, GridSelectorOption,
|
|
124
123
|
StyleOption, AspectRatioOption, DurationValue, AspectRatioTranslations, DurationOption,
|
|
@@ -14,7 +14,6 @@ import { PromptInput } from "./PromptInput";
|
|
|
14
14
|
import { GenerateButton } from "./buttons/GenerateButton";
|
|
15
15
|
import { ExamplePrompts } from "./prompts/ExamplePrompts";
|
|
16
16
|
import { StylePresetsGrid } from "./StylePresetsGrid";
|
|
17
|
-
import { GenerationProgressModal } from "./GenerationProgressModal";
|
|
18
17
|
import type { AIGenerationFormProps } from "./AIGenerationForm.types";
|
|
19
18
|
|
|
20
19
|
export const AIGenerationForm: React.FC<AIGenerationFormProps> = ({
|
|
@@ -35,10 +34,6 @@ export const AIGenerationForm: React.FC<AIGenerationFormProps> = ({
|
|
|
35
34
|
onGenerate,
|
|
36
35
|
isGenerating,
|
|
37
36
|
hideGenerateButton,
|
|
38
|
-
progress,
|
|
39
|
-
progressIcon,
|
|
40
|
-
isProgressModalVisible,
|
|
41
|
-
onCloseProgressModal,
|
|
42
37
|
generateButtonProps,
|
|
43
38
|
showAdvanced,
|
|
44
39
|
onAdvancedToggle,
|
|
@@ -155,17 +150,6 @@ export const AIGenerationForm: React.FC<AIGenerationFormProps> = ({
|
|
|
155
150
|
)}
|
|
156
151
|
</>
|
|
157
152
|
)}
|
|
158
|
-
|
|
159
|
-
{/* MANDATORY: Progress Modal shows automatically when isGenerating */}
|
|
160
|
-
<GenerationProgressModal
|
|
161
|
-
visible={isProgressModalVisible ?? isGenerating}
|
|
162
|
-
progress={progress ?? 0}
|
|
163
|
-
icon={progressIcon || "sparkles-outline"}
|
|
164
|
-
title={translations.progressTitle || translations.generatingButton}
|
|
165
|
-
message={translations.progressMessage || translations.progressHint}
|
|
166
|
-
onClose={onCloseProgressModal}
|
|
167
|
-
backgroundHint={onCloseProgressModal ? translations.progressBackgroundHint : undefined}
|
|
168
|
-
/>
|
|
169
153
|
</>
|
|
170
154
|
);
|
|
171
155
|
};
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export { GenerationProgressModal } from "./GenerationProgressModal";
|
|
2
1
|
export { GenerationProgressContent } from "./GenerationProgressContent";
|
|
3
2
|
export { GenerationProgressBar } from "./GenerationProgressBar";
|
|
4
3
|
export { PendingJobCard } from "./PendingJobCard";
|
|
@@ -10,11 +9,6 @@ export * from "./StylePresetsGrid";
|
|
|
10
9
|
export * from "./AIGenerationForm";
|
|
11
10
|
export * from "./AIGenerationForm.types";
|
|
12
11
|
|
|
13
|
-
export type {
|
|
14
|
-
GenerationProgressModalProps,
|
|
15
|
-
GenerationProgressRenderProps,
|
|
16
|
-
} from "./GenerationProgressModal";
|
|
17
|
-
|
|
18
12
|
export type { GenerationProgressContentProps } from "./GenerationProgressContent";
|
|
19
13
|
export type { GenerationProgressBarProps } from "./GenerationProgressBar";
|
|
20
14
|
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* DualImageFeatureLayout
|
|
3
3
|
* Centralized layout for all dual-image processing features (face-swap, ai-kiss, ai-hug)
|
|
4
|
-
* Handles:
|
|
4
|
+
* Handles: ScrollView, AIGenerationForm, AIGenerationResult, GenerationProgressContent
|
|
5
|
+
* Note: No Modal wrapper - shows fullscreen progress when processing (FutureUS pattern)
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
8
|
import React, { useCallback } from "react";
|
|
8
|
-
import { ScrollView, StyleSheet } from "react-native";
|
|
9
|
+
import { View, ScrollView, StyleSheet } from "react-native";
|
|
9
10
|
import {
|
|
10
11
|
useAppDesignTokens,
|
|
11
12
|
useResponsive,
|
|
@@ -13,7 +14,7 @@ import {
|
|
|
13
14
|
} from "@umituz/react-native-design-system";
|
|
14
15
|
import { AIGenerationForm } from "../components/AIGenerationForm";
|
|
15
16
|
import { AIGenerationResult } from "../components/display/AIGenerationResult";
|
|
16
|
-
import {
|
|
17
|
+
import { GenerationProgressContent } from "../components/GenerationProgressContent";
|
|
17
18
|
import type { DualImageFeatureLayoutProps } from "./types";
|
|
18
19
|
|
|
19
20
|
export const DualImageFeatureLayout: React.FC<DualImageFeatureLayoutProps> = ({
|
|
@@ -24,7 +25,6 @@ export const DualImageFeatureLayout: React.FC<DualImageFeatureLayoutProps> = ({
|
|
|
24
25
|
renderInput,
|
|
25
26
|
renderResult,
|
|
26
27
|
description,
|
|
27
|
-
renderProcessingModal,
|
|
28
28
|
children,
|
|
29
29
|
}) => {
|
|
30
30
|
const tokens = useAppDesignTokens();
|
|
@@ -47,19 +47,29 @@ export const DualImageFeatureLayout: React.FC<DualImageFeatureLayoutProps> = ({
|
|
|
47
47
|
void feature.selectTargetImage();
|
|
48
48
|
}, [feature]);
|
|
49
49
|
|
|
50
|
-
//
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
50
|
+
// Processing view - fullscreen (FutureUS pattern, no Modal)
|
|
51
|
+
if (feature.isProcessing) {
|
|
52
|
+
return (
|
|
53
|
+
<View
|
|
54
|
+
style={[
|
|
55
|
+
styles.processingContainer,
|
|
56
|
+
{ backgroundColor: tokens.colors.backgroundPrimary },
|
|
57
|
+
]}
|
|
58
|
+
>
|
|
59
|
+
<GenerationProgressContent
|
|
60
|
+
progress={feature.progress}
|
|
61
|
+
icon={modalIcon}
|
|
62
|
+
title={modalTranslations.title}
|
|
63
|
+
message={modalTranslations.message}
|
|
64
|
+
hint={modalTranslations.hint}
|
|
65
|
+
backgroundHint={modalTranslations.backgroundHint}
|
|
66
|
+
backgroundColor={tokens.colors.surface}
|
|
67
|
+
textColor={tokens.colors.textPrimary}
|
|
68
|
+
progressColor={tokens.colors.primary}
|
|
69
|
+
/>
|
|
70
|
+
</View>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
63
73
|
|
|
64
74
|
// Result view
|
|
65
75
|
if (feature.processedUrl) {
|
|
@@ -88,48 +98,42 @@ export const DualImageFeatureLayout: React.FC<DualImageFeatureLayoutProps> = ({
|
|
|
88
98
|
|
|
89
99
|
// Input view
|
|
90
100
|
return (
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
101
|
+
<ScrollView
|
|
102
|
+
style={[styles.container, { backgroundColor: tokens.colors.backgroundPrimary }]}
|
|
103
|
+
contentContainerStyle={styles.content}
|
|
104
|
+
showsVerticalScrollIndicator={false}
|
|
105
|
+
>
|
|
106
|
+
<AIGenerationForm
|
|
107
|
+
onGenerate={handleProcess}
|
|
108
|
+
isGenerating={feature.isProcessing}
|
|
109
|
+
progress={feature.progress}
|
|
110
|
+
translations={{
|
|
111
|
+
generateButton: translations.processButtonText,
|
|
112
|
+
generatingButton: translations.processingText,
|
|
113
|
+
progressTitle: translations.processingText,
|
|
114
|
+
}}
|
|
96
115
|
>
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}}
|
|
106
|
-
>
|
|
107
|
-
{description && (
|
|
108
|
-
<AtomicText
|
|
109
|
-
type="bodyLarge"
|
|
110
|
-
style={[styles.description, { color: tokens.colors.textSecondary }]}
|
|
111
|
-
>
|
|
112
|
-
{description}
|
|
113
|
-
</AtomicText>
|
|
114
|
-
)}
|
|
116
|
+
{description && (
|
|
117
|
+
<AtomicText
|
|
118
|
+
type="bodyLarge"
|
|
119
|
+
style={[styles.description, { color: tokens.colors.textSecondary }]}
|
|
120
|
+
>
|
|
121
|
+
{description}
|
|
122
|
+
</AtomicText>
|
|
123
|
+
)}
|
|
115
124
|
|
|
116
|
-
|
|
125
|
+
{children}
|
|
117
126
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
{renderProcessingModal
|
|
130
|
-
? renderProcessingModal({ visible: feature.isProcessing, progress: feature.progress })
|
|
131
|
-
: defaultModal}
|
|
132
|
-
</>
|
|
127
|
+
{renderInput({
|
|
128
|
+
sourceImageUri: feature.sourceImageUri,
|
|
129
|
+
targetImageUri: feature.targetImageUri,
|
|
130
|
+
onSelectSource: handleSelectSource,
|
|
131
|
+
onSelectTarget: handleSelectTarget,
|
|
132
|
+
isDisabled: feature.isProcessing,
|
|
133
|
+
isProcessing: feature.isProcessing,
|
|
134
|
+
})}
|
|
135
|
+
</AIGenerationForm>
|
|
136
|
+
</ScrollView>
|
|
133
137
|
);
|
|
134
138
|
};
|
|
135
139
|
|
|
@@ -146,4 +150,9 @@ const styles = StyleSheet.create({
|
|
|
146
150
|
marginBottom: 24,
|
|
147
151
|
lineHeight: 24,
|
|
148
152
|
},
|
|
153
|
+
processingContainer: {
|
|
154
|
+
flex: 1,
|
|
155
|
+
justifyContent: "center",
|
|
156
|
+
alignItems: "center",
|
|
157
|
+
},
|
|
149
158
|
});
|
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* DualImageVideoFeatureLayout
|
|
3
3
|
* Centralized layout for dual-image video features (ai-kiss, ai-hug)
|
|
4
|
-
* Handles:
|
|
4
|
+
* Handles: ScrollView, AIGenerationForm, AIGenerationResult, GenerationProgressContent
|
|
5
|
+
* Note: No Modal wrapper - shows fullscreen progress when processing (FutureUS pattern)
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
8
|
import React, { useCallback } from "react";
|
|
8
|
-
import { ScrollView, StyleSheet } from "react-native";
|
|
9
|
+
import { View, ScrollView, StyleSheet } from "react-native";
|
|
9
10
|
import {
|
|
10
11
|
useAppDesignTokens,
|
|
11
12
|
AtomicText,
|
|
12
13
|
} from "@umituz/react-native-design-system";
|
|
13
14
|
import { AIGenerationForm } from "../components/AIGenerationForm";
|
|
14
15
|
import { AIGenerationResult } from "../components/display/AIGenerationResult";
|
|
15
|
-
import {
|
|
16
|
+
import { GenerationProgressContent } from "../components/GenerationProgressContent";
|
|
16
17
|
import type { DualImageVideoFeatureLayoutProps } from "./types";
|
|
17
18
|
|
|
18
19
|
export const DualImageVideoFeatureLayout: React.FC<DualImageVideoFeatureLayoutProps> = ({
|
|
@@ -22,7 +23,6 @@ export const DualImageVideoFeatureLayout: React.FC<DualImageVideoFeatureLayoutPr
|
|
|
22
23
|
modalIcon = "sparkles",
|
|
23
24
|
renderInput,
|
|
24
25
|
description,
|
|
25
|
-
renderProcessingModal,
|
|
26
26
|
children,
|
|
27
27
|
}) => {
|
|
28
28
|
const tokens = useAppDesignTokens();
|
|
@@ -43,19 +43,29 @@ export const DualImageVideoFeatureLayout: React.FC<DualImageVideoFeatureLayoutPr
|
|
|
43
43
|
void feature.selectTargetImage();
|
|
44
44
|
}, [feature]);
|
|
45
45
|
|
|
46
|
-
//
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
46
|
+
// Processing view - fullscreen (FutureUS pattern, no Modal)
|
|
47
|
+
if (feature.isProcessing) {
|
|
48
|
+
return (
|
|
49
|
+
<View
|
|
50
|
+
style={[
|
|
51
|
+
styles.processingContainer,
|
|
52
|
+
{ backgroundColor: tokens.colors.backgroundPrimary },
|
|
53
|
+
]}
|
|
54
|
+
>
|
|
55
|
+
<GenerationProgressContent
|
|
56
|
+
progress={feature.progress}
|
|
57
|
+
icon={modalIcon}
|
|
58
|
+
title={modalTranslations.title}
|
|
59
|
+
message={modalTranslations.message}
|
|
60
|
+
hint={modalTranslations.hint}
|
|
61
|
+
backgroundHint={modalTranslations.backgroundHint}
|
|
62
|
+
backgroundColor={tokens.colors.surface}
|
|
63
|
+
textColor={tokens.colors.textPrimary}
|
|
64
|
+
progressColor={tokens.colors.primary}
|
|
65
|
+
/>
|
|
66
|
+
</View>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
59
69
|
|
|
60
70
|
// Result view (video features show result without embedded content)
|
|
61
71
|
if (feature.processedVideoUrl) {
|
|
@@ -82,48 +92,42 @@ export const DualImageVideoFeatureLayout: React.FC<DualImageVideoFeatureLayoutPr
|
|
|
82
92
|
|
|
83
93
|
// Input view
|
|
84
94
|
return (
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
95
|
+
<ScrollView
|
|
96
|
+
style={[styles.container, { backgroundColor: tokens.colors.backgroundPrimary }]}
|
|
97
|
+
contentContainerStyle={styles.content}
|
|
98
|
+
showsVerticalScrollIndicator={false}
|
|
99
|
+
>
|
|
100
|
+
<AIGenerationForm
|
|
101
|
+
onGenerate={handleProcess}
|
|
102
|
+
isGenerating={feature.isProcessing}
|
|
103
|
+
progress={feature.progress}
|
|
104
|
+
translations={{
|
|
105
|
+
generateButton: translations.processButtonText,
|
|
106
|
+
generatingButton: translations.processingText,
|
|
107
|
+
progressTitle: translations.processingText,
|
|
108
|
+
}}
|
|
90
109
|
>
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
}}
|
|
100
|
-
>
|
|
101
|
-
{description && (
|
|
102
|
-
<AtomicText
|
|
103
|
-
type="bodyLarge"
|
|
104
|
-
style={[styles.description, { color: tokens.colors.textSecondary }]}
|
|
105
|
-
>
|
|
106
|
-
{description}
|
|
107
|
-
</AtomicText>
|
|
108
|
-
)}
|
|
110
|
+
{description && (
|
|
111
|
+
<AtomicText
|
|
112
|
+
type="bodyLarge"
|
|
113
|
+
style={[styles.description, { color: tokens.colors.textSecondary }]}
|
|
114
|
+
>
|
|
115
|
+
{description}
|
|
116
|
+
</AtomicText>
|
|
117
|
+
)}
|
|
109
118
|
|
|
110
|
-
|
|
119
|
+
{children}
|
|
111
120
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
{renderProcessingModal
|
|
124
|
-
? renderProcessingModal({ visible: feature.isProcessing, progress: feature.progress })
|
|
125
|
-
: defaultModal}
|
|
126
|
-
</>
|
|
121
|
+
{renderInput({
|
|
122
|
+
sourceImageUri: feature.sourceImageUri,
|
|
123
|
+
targetImageUri: feature.targetImageUri,
|
|
124
|
+
onSelectSource: handleSelectSource,
|
|
125
|
+
onSelectTarget: handleSelectTarget,
|
|
126
|
+
isDisabled: feature.isProcessing,
|
|
127
|
+
isProcessing: feature.isProcessing,
|
|
128
|
+
})}
|
|
129
|
+
</AIGenerationForm>
|
|
130
|
+
</ScrollView>
|
|
127
131
|
);
|
|
128
132
|
};
|
|
129
133
|
|
|
@@ -140,4 +144,9 @@ const styles = StyleSheet.create({
|
|
|
140
144
|
marginBottom: 24,
|
|
141
145
|
lineHeight: 24,
|
|
142
146
|
},
|
|
147
|
+
processingContainer: {
|
|
148
|
+
flex: 1,
|
|
149
|
+
justifyContent: "center",
|
|
150
|
+
alignItems: "center",
|
|
151
|
+
},
|
|
143
152
|
});
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SingleImageFeatureLayout
|
|
3
3
|
* Centralized layout for all single-image processing features
|
|
4
|
-
* Handles:
|
|
4
|
+
* Handles: ScrollView, AIGenerationForm, AIGenerationResult, GenerationProgressContent
|
|
5
|
+
* Note: No Modal wrapper - shows fullscreen progress when processing (FutureUS pattern)
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
8
|
import React, { useCallback } from "react";
|
|
8
|
-
import { ScrollView, StyleSheet } from "react-native";
|
|
9
|
+
import { View, ScrollView, StyleSheet } from "react-native";
|
|
9
10
|
import {
|
|
10
11
|
useAppDesignTokens,
|
|
11
12
|
useResponsive,
|
|
@@ -13,7 +14,7 @@ import {
|
|
|
13
14
|
} from "@umituz/react-native-design-system";
|
|
14
15
|
import { AIGenerationForm } from "../components/AIGenerationForm";
|
|
15
16
|
import { AIGenerationResult } from "../components/display/AIGenerationResult";
|
|
16
|
-
import {
|
|
17
|
+
import { GenerationProgressContent } from "../components/GenerationProgressContent";
|
|
17
18
|
import type { SingleImageFeatureLayoutProps } from "./types";
|
|
18
19
|
|
|
19
20
|
export const SingleImageFeatureLayout: React.FC<SingleImageFeatureLayoutProps> = ({
|
|
@@ -25,7 +26,6 @@ export const SingleImageFeatureLayout: React.FC<SingleImageFeatureLayoutProps> =
|
|
|
25
26
|
renderResult,
|
|
26
27
|
renderCustomResult,
|
|
27
28
|
description,
|
|
28
|
-
renderProcessingModal,
|
|
29
29
|
children,
|
|
30
30
|
}) => {
|
|
31
31
|
const tokens = useAppDesignTokens();
|
|
@@ -44,19 +44,29 @@ export const SingleImageFeatureLayout: React.FC<SingleImageFeatureLayoutProps> =
|
|
|
44
44
|
void feature.selectImage();
|
|
45
45
|
}, [feature]);
|
|
46
46
|
|
|
47
|
-
//
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
47
|
+
// Processing view - fullscreen (FutureUS pattern, no Modal)
|
|
48
|
+
if (feature.isProcessing) {
|
|
49
|
+
return (
|
|
50
|
+
<View
|
|
51
|
+
style={[
|
|
52
|
+
styles.processingContainer,
|
|
53
|
+
{ backgroundColor: tokens.colors.backgroundPrimary },
|
|
54
|
+
]}
|
|
55
|
+
>
|
|
56
|
+
<GenerationProgressContent
|
|
57
|
+
progress={feature.progress}
|
|
58
|
+
icon={modalIcon}
|
|
59
|
+
title={modalTranslations.title}
|
|
60
|
+
message={modalTranslations.message}
|
|
61
|
+
hint={modalTranslations.hint}
|
|
62
|
+
backgroundHint={modalTranslations.backgroundHint}
|
|
63
|
+
backgroundColor={tokens.colors.surface}
|
|
64
|
+
textColor={tokens.colors.textPrimary}
|
|
65
|
+
progressColor={tokens.colors.primary}
|
|
66
|
+
/>
|
|
67
|
+
</View>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
60
70
|
|
|
61
71
|
// Custom result view (for comparison sliders, etc.)
|
|
62
72
|
if (feature.processedUrl && renderCustomResult && feature.imageUri) {
|
|
@@ -104,46 +114,40 @@ export const SingleImageFeatureLayout: React.FC<SingleImageFeatureLayoutProps> =
|
|
|
104
114
|
|
|
105
115
|
// Input view
|
|
106
116
|
return (
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
117
|
+
<ScrollView
|
|
118
|
+
style={[styles.container, { backgroundColor: tokens.colors.backgroundPrimary }]}
|
|
119
|
+
contentContainerStyle={styles.content}
|
|
120
|
+
showsVerticalScrollIndicator={false}
|
|
121
|
+
>
|
|
122
|
+
<AIGenerationForm
|
|
123
|
+
onGenerate={handleProcess}
|
|
124
|
+
isGenerating={feature.isProcessing}
|
|
125
|
+
progress={feature.progress}
|
|
126
|
+
translations={{
|
|
127
|
+
generateButton: translations.processButtonText,
|
|
128
|
+
generatingButton: translations.processingText,
|
|
129
|
+
progressTitle: translations.processingText,
|
|
130
|
+
}}
|
|
112
131
|
>
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}}
|
|
122
|
-
>
|
|
123
|
-
{description && (
|
|
124
|
-
<AtomicText
|
|
125
|
-
type="bodyLarge"
|
|
126
|
-
style={[styles.description, { color: tokens.colors.textSecondary }]}
|
|
127
|
-
>
|
|
128
|
-
{description}
|
|
129
|
-
</AtomicText>
|
|
130
|
-
)}
|
|
132
|
+
{description && (
|
|
133
|
+
<AtomicText
|
|
134
|
+
type="bodyLarge"
|
|
135
|
+
style={[styles.description, { color: tokens.colors.textSecondary }]}
|
|
136
|
+
>
|
|
137
|
+
{description}
|
|
138
|
+
</AtomicText>
|
|
139
|
+
)}
|
|
131
140
|
|
|
132
|
-
|
|
141
|
+
{children}
|
|
133
142
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
{renderProcessingModal
|
|
144
|
-
? renderProcessingModal({ visible: feature.isProcessing, progress: feature.progress })
|
|
145
|
-
: defaultModal}
|
|
146
|
-
</>
|
|
143
|
+
{renderInput({
|
|
144
|
+
imageUri: feature.imageUri,
|
|
145
|
+
onSelect: handleSelectImage,
|
|
146
|
+
isDisabled: feature.isProcessing,
|
|
147
|
+
isProcessing: feature.isProcessing,
|
|
148
|
+
})}
|
|
149
|
+
</AIGenerationForm>
|
|
150
|
+
</ScrollView>
|
|
147
151
|
);
|
|
148
152
|
};
|
|
149
153
|
|
|
@@ -160,4 +164,9 @@ const styles = StyleSheet.create({
|
|
|
160
164
|
marginBottom: 24,
|
|
161
165
|
lineHeight: 24,
|
|
162
166
|
},
|
|
167
|
+
processingContainer: {
|
|
168
|
+
flex: 1,
|
|
169
|
+
justifyContent: "center",
|
|
170
|
+
alignItems: "center",
|
|
171
|
+
},
|
|
163
172
|
});
|