@umituz/react-native-ai-generation-content 1.17.17 → 1.17.18
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 -4
- package/src/domains/creations/presentation/components/CreationDetail/DetailImage.tsx +14 -14
- package/src/domains/creations/presentation/components/CreationDetail/DetailVideo.tsx +51 -58
- package/src/domains/creations/presentation/screens/CreationDetailScreen.tsx +36 -29
- package/src/features/text-to-image/index.ts +19 -19
- package/src/features/text-to-image/presentation/components/{PromptInput.tsx → TextToImagePromptInput.tsx} +3 -3
- package/src/features/text-to-image/presentation/components/index.ts +21 -18
- package/src/features/text-to-image/presentation/hooks/useGeneration.ts +4 -5
- package/src/features/text-to-voice/domain/types/component.types.ts +91 -0
- package/src/features/text-to-voice/domain/types/config.types.ts +34 -0
- package/src/features/text-to-voice/domain/types/form.types.ts +39 -0
- package/src/features/text-to-voice/domain/types/generation.types.ts +43 -0
- package/src/features/text-to-voice/domain/types/index.ts +31 -3
- package/src/features/text-to-voice/infrastructure/services/text-to-voice-executor.ts +2 -10
- package/src/features/text-to-voice/domain/types/text-to-voice.types.ts +0 -65
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.18",
|
|
4
4
|
"description": "Provider-agnostic AI generation orchestration for React Native",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -101,8 +101,5 @@
|
|
|
101
101
|
},
|
|
102
102
|
"publishConfig": {
|
|
103
103
|
"access": "public"
|
|
104
|
-
},
|
|
105
|
-
"dependencies": {
|
|
106
|
-
"@umituz/react-native-ai-generation-content": "^1.17.14"
|
|
107
104
|
}
|
|
108
105
|
}
|
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
|
|
2
1
|
import React from 'react';
|
|
3
|
-
import { View, StyleSheet,
|
|
4
|
-
import { useAppDesignTokens
|
|
2
|
+
import { View, StyleSheet, useWindowDimensions } from 'react-native';
|
|
3
|
+
import { useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
4
|
+
import { Image } from 'expo-image';
|
|
5
5
|
|
|
6
6
|
interface DetailImageProps {
|
|
7
7
|
readonly uri: string;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
const
|
|
10
|
+
const HORIZONTAL_PADDING = 16;
|
|
11
|
+
const ASPECT_RATIO = 16 / 9;
|
|
11
12
|
|
|
12
13
|
export const DetailImage: React.FC<DetailImageProps> = ({ uri }) => {
|
|
13
14
|
const tokens = useAppDesignTokens();
|
|
14
|
-
const
|
|
15
|
+
const { width } = useWindowDimensions();
|
|
16
|
+
const imageWidth = width - (HORIZONTAL_PADDING * 2);
|
|
17
|
+
const imageHeight = imageWidth / ASPECT_RATIO;
|
|
15
18
|
|
|
16
19
|
return (
|
|
17
20
|
<View style={styles.container}>
|
|
18
|
-
<View style={styles.frame}>
|
|
19
|
-
<Image source={{ uri }} style={styles.image}
|
|
21
|
+
<View style={[styles.frame, { width: imageWidth, height: imageHeight, backgroundColor: tokens.colors.surface }]}>
|
|
22
|
+
<Image source={{ uri }} style={styles.image} contentFit="cover" />
|
|
20
23
|
</View>
|
|
21
24
|
</View>
|
|
22
25
|
);
|
|
23
26
|
};
|
|
24
27
|
|
|
25
|
-
const
|
|
28
|
+
const styles = StyleSheet.create({
|
|
26
29
|
container: {
|
|
27
|
-
paddingHorizontal:
|
|
28
|
-
marginVertical:
|
|
30
|
+
paddingHorizontal: HORIZONTAL_PADDING,
|
|
31
|
+
marginVertical: 16,
|
|
29
32
|
},
|
|
30
33
|
frame: {
|
|
31
|
-
|
|
32
|
-
height: width - (tokens.spacing.lg * 2),
|
|
33
|
-
borderRadius: 24,
|
|
34
|
+
borderRadius: 16,
|
|
34
35
|
overflow: 'hidden',
|
|
35
|
-
backgroundColor: tokens.colors.surface,
|
|
36
36
|
},
|
|
37
37
|
image: {
|
|
38
38
|
width: '100%',
|
|
@@ -4,12 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import React, { useState, useCallback } from "react";
|
|
7
|
-
import { View, StyleSheet,
|
|
8
|
-
import {
|
|
9
|
-
useAppDesignTokens,
|
|
10
|
-
AtomicIcon,
|
|
11
|
-
type DesignTokens,
|
|
12
|
-
} from "@umituz/react-native-design-system";
|
|
7
|
+
import { View, StyleSheet, TouchableOpacity, useWindowDimensions } from "react-native";
|
|
8
|
+
import { useAppDesignTokens, AtomicIcon } from "@umituz/react-native-design-system";
|
|
13
9
|
import { Image } from "expo-image";
|
|
14
10
|
import { useVideoPlayer, VideoView } from "expo-video";
|
|
15
11
|
|
|
@@ -18,14 +14,17 @@ interface DetailVideoProps {
|
|
|
18
14
|
readonly thumbnailUrl?: string;
|
|
19
15
|
}
|
|
20
16
|
|
|
21
|
-
const
|
|
17
|
+
const HORIZONTAL_PADDING = 16;
|
|
18
|
+
const ASPECT_RATIO = 16 / 9;
|
|
22
19
|
|
|
23
20
|
export const DetailVideo: React.FC<DetailVideoProps> = ({
|
|
24
21
|
videoUrl,
|
|
25
22
|
thumbnailUrl,
|
|
26
23
|
}) => {
|
|
27
24
|
const tokens = useAppDesignTokens();
|
|
28
|
-
const
|
|
25
|
+
const { width } = useWindowDimensions();
|
|
26
|
+
const videoWidth = width - (HORIZONTAL_PADDING * 2);
|
|
27
|
+
const videoHeight = videoWidth / ASPECT_RATIO;
|
|
29
28
|
const [isPlaying, setIsPlaying] = useState(false);
|
|
30
29
|
|
|
31
30
|
const player = useVideoPlayer(videoUrl, (p) => {
|
|
@@ -39,7 +38,7 @@ export const DetailVideo: React.FC<DetailVideoProps> = ({
|
|
|
39
38
|
|
|
40
39
|
return (
|
|
41
40
|
<View style={styles.container}>
|
|
42
|
-
<View style={styles.frame}>
|
|
41
|
+
<View style={[styles.frame, { width: videoWidth, height: videoHeight, backgroundColor: tokens.colors.surface }]}>
|
|
43
42
|
{isPlaying ? (
|
|
44
43
|
<VideoView
|
|
45
44
|
player={player}
|
|
@@ -60,10 +59,10 @@ export const DetailVideo: React.FC<DetailVideoProps> = ({
|
|
|
60
59
|
contentFit="cover"
|
|
61
60
|
/>
|
|
62
61
|
) : (
|
|
63
|
-
<View style={styles.placeholder} />
|
|
62
|
+
<View style={[styles.placeholder, { backgroundColor: tokens.colors.surfaceSecondary }]} />
|
|
64
63
|
)}
|
|
65
64
|
<View style={styles.playButtonContainer}>
|
|
66
|
-
<View style={styles.playButton}>
|
|
65
|
+
<View style={[styles.playButton, { backgroundColor: tokens.colors.primary }]}>
|
|
67
66
|
<AtomicIcon name="play" customSize={32} color="onPrimary" />
|
|
68
67
|
</View>
|
|
69
68
|
</View>
|
|
@@ -74,50 +73,44 @@ export const DetailVideo: React.FC<DetailVideoProps> = ({
|
|
|
74
73
|
);
|
|
75
74
|
};
|
|
76
75
|
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
backgroundColor: tokens.colors.primary,
|
|
119
|
-
justifyContent: "center",
|
|
120
|
-
alignItems: "center",
|
|
121
|
-
paddingLeft: 4,
|
|
122
|
-
},
|
|
123
|
-
});
|
|
76
|
+
const styles = StyleSheet.create({
|
|
77
|
+
container: {
|
|
78
|
+
paddingHorizontal: HORIZONTAL_PADDING,
|
|
79
|
+
marginVertical: 16,
|
|
80
|
+
},
|
|
81
|
+
frame: {
|
|
82
|
+
borderRadius: 16,
|
|
83
|
+
overflow: "hidden",
|
|
84
|
+
},
|
|
85
|
+
video: {
|
|
86
|
+
width: "100%",
|
|
87
|
+
height: "100%",
|
|
88
|
+
},
|
|
89
|
+
thumbnailContainer: {
|
|
90
|
+
width: "100%",
|
|
91
|
+
height: "100%",
|
|
92
|
+
justifyContent: "center",
|
|
93
|
+
alignItems: "center",
|
|
94
|
+
},
|
|
95
|
+
thumbnail: {
|
|
96
|
+
width: "100%",
|
|
97
|
+
height: "100%",
|
|
98
|
+
},
|
|
99
|
+
placeholder: {
|
|
100
|
+
width: "100%",
|
|
101
|
+
height: "100%",
|
|
102
|
+
},
|
|
103
|
+
playButtonContainer: {
|
|
104
|
+
...StyleSheet.absoluteFillObject,
|
|
105
|
+
justifyContent: "center",
|
|
106
|
+
alignItems: "center",
|
|
107
|
+
},
|
|
108
|
+
playButton: {
|
|
109
|
+
width: 64,
|
|
110
|
+
height: 64,
|
|
111
|
+
borderRadius: 32,
|
|
112
|
+
justifyContent: "center",
|
|
113
|
+
alignItems: "center",
|
|
114
|
+
paddingLeft: 4,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useMemo } from 'react';
|
|
2
|
-
import { StyleSheet } from 'react-native';
|
|
3
|
-
import {
|
|
2
|
+
import { View, ScrollView, StyleSheet } from 'react-native';
|
|
3
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
4
|
+
import { useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
4
5
|
import type { Creation } from '../../domain/entities/Creation';
|
|
5
6
|
import { hasVideoContent, getPreviewUrl } from '../../domain/utils';
|
|
6
7
|
import { DetailHeader } from '../components/CreationDetail/DetailHeader';
|
|
@@ -37,6 +38,7 @@ export const CreationDetailScreen: React.FC<CreationDetailScreenProps> = ({
|
|
|
37
38
|
t
|
|
38
39
|
}) => {
|
|
39
40
|
const tokens = useAppDesignTokens();
|
|
41
|
+
const insets = useSafeAreaInsets();
|
|
40
42
|
const { getLocalizedTitle } = useCreationsProvider();
|
|
41
43
|
|
|
42
44
|
// Extract data safely
|
|
@@ -57,48 +59,53 @@ export const CreationDetailScreen: React.FC<CreationDetailScreenProps> = ({
|
|
|
57
59
|
return false;
|
|
58
60
|
}, [creation.type, creation.output]);
|
|
59
61
|
|
|
60
|
-
const styles = useStyles(tokens);
|
|
61
|
-
|
|
62
62
|
// Get video URL and thumbnail for video content
|
|
63
63
|
const videoUrl = creation.output?.videoUrl || creation.uri;
|
|
64
64
|
const thumbnailUrl = getPreviewUrl(creation.output) || undefined;
|
|
65
65
|
|
|
66
66
|
return (
|
|
67
|
-
<
|
|
68
|
-
|
|
69
|
-
edges={['top', 'bottom']}
|
|
70
|
-
backgroundColor={tokens.colors.background}
|
|
71
|
-
header={
|
|
67
|
+
<View style={[styles.container, { backgroundColor: tokens.colors.background }]}>
|
|
68
|
+
<View style={{ paddingTop: insets.top }}>
|
|
72
69
|
<DetailHeader
|
|
73
70
|
title={title}
|
|
74
71
|
date={date}
|
|
75
72
|
onClose={onClose}
|
|
76
73
|
/>
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
74
|
+
</View>
|
|
75
|
+
<ScrollView
|
|
76
|
+
style={styles.scrollView}
|
|
77
|
+
contentContainerStyle={[styles.scrollContent, { paddingBottom: insets.bottom + 32 }]}
|
|
78
|
+
showsVerticalScrollIndicator={false}
|
|
79
|
+
>
|
|
80
|
+
{isVideo ? (
|
|
81
|
+
<DetailVideo videoUrl={videoUrl} thumbnailUrl={thumbnailUrl} />
|
|
82
|
+
) : (
|
|
83
|
+
<DetailImage uri={creation.uri} />
|
|
84
|
+
)}
|
|
85
85
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
{story ? (
|
|
87
|
+
<DetailStory story={story} />
|
|
88
|
+
) : null}
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
90
|
+
<DetailActions
|
|
91
|
+
onShare={() => onShare(creation)}
|
|
92
|
+
onDelete={() => onDelete(creation)}
|
|
93
|
+
shareLabel={t("result.shareButton")}
|
|
94
|
+
deleteLabel={t("common.delete")}
|
|
95
|
+
/>
|
|
96
|
+
</ScrollView>
|
|
97
|
+
</View>
|
|
97
98
|
);
|
|
98
99
|
};
|
|
99
100
|
|
|
100
|
-
const
|
|
101
|
+
const styles = StyleSheet.create({
|
|
102
|
+
container: {
|
|
103
|
+
flex: 1,
|
|
104
|
+
},
|
|
105
|
+
scrollView: {
|
|
106
|
+
flex: 1,
|
|
107
|
+
},
|
|
101
108
|
scrollContent: {
|
|
102
|
-
|
|
109
|
+
paddingTop: 8,
|
|
103
110
|
},
|
|
104
111
|
});
|
|
@@ -88,28 +88,28 @@ export type {
|
|
|
88
88
|
// =============================================================================
|
|
89
89
|
|
|
90
90
|
export {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
91
|
+
TextToImagePromptInput,
|
|
92
|
+
TextToImageExamplePrompts,
|
|
93
|
+
TextToImageNumImagesSelector,
|
|
94
|
+
TextToImageStyleSelector,
|
|
95
|
+
TextToImageAspectRatioSelector,
|
|
96
|
+
TextToImageSizeSelector,
|
|
97
|
+
TextToImageOutputFormatSelector,
|
|
98
98
|
TextToImageGenerateButton,
|
|
99
|
-
|
|
99
|
+
TextToImageSettingsSheet,
|
|
100
100
|
} from "./presentation";
|
|
101
101
|
|
|
102
102
|
export type {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
103
|
+
TextToImagePromptInputProps,
|
|
104
|
+
TextToImageExamplePromptsProps,
|
|
105
|
+
TextToImageNumImagesSelectorProps,
|
|
106
|
+
TextToImageStyleSelectorProps,
|
|
107
|
+
TextToImageAspectRatioSelectorProps,
|
|
108
|
+
TextToImageAspectRatioOption,
|
|
109
|
+
TextToImageSizeSelectorProps,
|
|
110
|
+
TextToImageSizeOption,
|
|
111
|
+
TextToImageOutputFormatSelectorProps,
|
|
112
|
+
TextToImageOutputFormatOption,
|
|
113
113
|
TextToImageGenerateButtonProps,
|
|
114
|
-
|
|
114
|
+
TextToImageSettingsSheetProps,
|
|
115
115
|
} from "./presentation";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Prompt Input Component
|
|
2
|
+
* Text-to-Image Prompt Input Component
|
|
3
3
|
* Text input for entering generation prompts
|
|
4
4
|
*/
|
|
5
5
|
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
useAppDesignTokens,
|
|
11
11
|
} from "@umituz/react-native-design-system";
|
|
12
12
|
|
|
13
|
-
export interface
|
|
13
|
+
export interface TextToImagePromptInputProps {
|
|
14
14
|
value: string;
|
|
15
15
|
onChangeText: (text: string) => void;
|
|
16
16
|
label: string;
|
|
@@ -20,7 +20,7 @@ export interface PromptInputProps {
|
|
|
20
20
|
maxLength?: number;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
export const
|
|
23
|
+
export const TextToImagePromptInput: React.FC<TextToImagePromptInputProps> = ({
|
|
24
24
|
value,
|
|
25
25
|
onChangeText,
|
|
26
26
|
label,
|
|
@@ -4,32 +4,35 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
// Input Components
|
|
7
|
-
export {
|
|
8
|
-
export type {
|
|
7
|
+
export { TextToImagePromptInput } from "./TextToImagePromptInput";
|
|
8
|
+
export type { TextToImagePromptInputProps } from "./TextToImagePromptInput";
|
|
9
9
|
|
|
10
|
-
export { ExamplePrompts } from "./ExamplePrompts";
|
|
11
|
-
export type { ExamplePromptsProps } from "./ExamplePrompts";
|
|
10
|
+
export { ExamplePrompts as TextToImageExamplePrompts } from "./ExamplePrompts";
|
|
11
|
+
export type { ExamplePromptsProps as TextToImageExamplePromptsProps } from "./ExamplePrompts";
|
|
12
12
|
|
|
13
13
|
// Selector Components
|
|
14
|
-
export { NumImagesSelector } from "./NumImagesSelector";
|
|
15
|
-
export type { NumImagesSelectorProps } from "./NumImagesSelector";
|
|
14
|
+
export { NumImagesSelector as TextToImageNumImagesSelector } from "./NumImagesSelector";
|
|
15
|
+
export type { NumImagesSelectorProps as TextToImageNumImagesSelectorProps } from "./NumImagesSelector";
|
|
16
16
|
|
|
17
|
-
export { StyleSelector } from "./StyleSelector";
|
|
18
|
-
export type { StyleSelectorProps } from "./StyleSelector";
|
|
17
|
+
export { StyleSelector as TextToImageStyleSelector } from "./StyleSelector";
|
|
18
|
+
export type { StyleSelectorProps as TextToImageStyleSelectorProps } from "./StyleSelector";
|
|
19
19
|
|
|
20
|
-
export { AspectRatioSelector } from "./AspectRatioSelector";
|
|
20
|
+
export { AspectRatioSelector as TextToImageAspectRatioSelector } from "./AspectRatioSelector";
|
|
21
21
|
export type {
|
|
22
|
-
AspectRatioSelectorProps,
|
|
23
|
-
AspectRatioOption,
|
|
22
|
+
AspectRatioSelectorProps as TextToImageAspectRatioSelectorProps,
|
|
23
|
+
AspectRatioOption as TextToImageAspectRatioOption,
|
|
24
24
|
} from "./AspectRatioSelector";
|
|
25
25
|
|
|
26
|
-
export { ImageSizeSelector } from "./ImageSizeSelector";
|
|
27
|
-
export type {
|
|
26
|
+
export { ImageSizeSelector as TextToImageSizeSelector } from "./ImageSizeSelector";
|
|
27
|
+
export type {
|
|
28
|
+
ImageSizeSelectorProps as TextToImageSizeSelectorProps,
|
|
29
|
+
ImageSizeOption as TextToImageSizeOption,
|
|
30
|
+
} from "./ImageSizeSelector";
|
|
28
31
|
|
|
29
|
-
export { OutputFormatSelector } from "./OutputFormatSelector";
|
|
32
|
+
export { OutputFormatSelector as TextToImageOutputFormatSelector } from "./OutputFormatSelector";
|
|
30
33
|
export type {
|
|
31
|
-
OutputFormatSelectorProps,
|
|
32
|
-
OutputFormatOption,
|
|
34
|
+
OutputFormatSelectorProps as TextToImageOutputFormatSelectorProps,
|
|
35
|
+
OutputFormatOption as TextToImageOutputFormatOption,
|
|
33
36
|
} from "./OutputFormatSelector";
|
|
34
37
|
|
|
35
38
|
// Action Components
|
|
@@ -37,5 +40,5 @@ export { TextToImageGenerateButton } from "./TextToImageGenerateButton";
|
|
|
37
40
|
export type { TextToImageGenerateButtonProps } from "./TextToImageGenerateButton";
|
|
38
41
|
|
|
39
42
|
// Sheet Components
|
|
40
|
-
export { SettingsSheet } from "./SettingsSheet";
|
|
41
|
-
export type { SettingsSheetProps } from "./SettingsSheet";
|
|
43
|
+
export { SettingsSheet as TextToImageSettingsSheet } from "./SettingsSheet";
|
|
44
|
+
export type { SettingsSheetProps as TextToImageSettingsSheetProps } from "./SettingsSheet";
|
|
@@ -76,16 +76,15 @@ export function useGeneration(options: UseGenerationOptions): UseGenerationRetur
|
|
|
76
76
|
try {
|
|
77
77
|
const result = await callbacks.executeGeneration(request);
|
|
78
78
|
|
|
79
|
-
if (result.success) {
|
|
79
|
+
if (result.success === true) {
|
|
80
80
|
callbacks.onSuccess?.(result.imageUrls);
|
|
81
81
|
onPromptCleared?.();
|
|
82
|
+
setGenerationState({ isGenerating: false, progress: 100, error: null });
|
|
82
83
|
} else {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
callbacks.onError?.(errorMessage);
|
|
84
|
+
setGenerationState({ isGenerating: false, progress: 0, error: result.error });
|
|
85
|
+
callbacks.onError?.(result.error);
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
setGenerationState({ isGenerating: false, progress: 100, error: null });
|
|
89
88
|
return result;
|
|
90
89
|
} catch (error) {
|
|
91
90
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text-to-Voice Component Types
|
|
3
|
+
* Props types for UI components
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { ReactNode } from "react";
|
|
7
|
+
import type { StyleProp, ViewStyle } from "react-native";
|
|
8
|
+
|
|
9
|
+
export interface TextToVoiceTextInputProps {
|
|
10
|
+
value: string;
|
|
11
|
+
onChangeText: (text: string) => void;
|
|
12
|
+
maxLength?: number;
|
|
13
|
+
labelKey: string;
|
|
14
|
+
placeholderKey: string;
|
|
15
|
+
characterCountKey: string;
|
|
16
|
+
style?: StyleProp<ViewStyle>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface TextToVoiceOptionalInputProps {
|
|
20
|
+
title: string;
|
|
21
|
+
value: string;
|
|
22
|
+
onChangeText: (text: string) => void;
|
|
23
|
+
placeholder: string;
|
|
24
|
+
hint: string;
|
|
25
|
+
style?: StyleProp<ViewStyle>;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface TextToVoiceExamplePromptsProps {
|
|
29
|
+
prompts: string[];
|
|
30
|
+
onSelectPrompt: (prompt: string) => void;
|
|
31
|
+
labelKey: string;
|
|
32
|
+
style?: StyleProp<ViewStyle>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface TextToVoiceGenerateButtonProps {
|
|
36
|
+
isGenerating: boolean;
|
|
37
|
+
progress: number;
|
|
38
|
+
disabled: boolean;
|
|
39
|
+
onPress: () => void;
|
|
40
|
+
buttonTextKey: string;
|
|
41
|
+
generatingTextKey: string;
|
|
42
|
+
style?: StyleProp<ViewStyle>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface TextToVoiceAudioPlayerProps {
|
|
46
|
+
audioUrl: string;
|
|
47
|
+
onPlay: () => void;
|
|
48
|
+
successTextKey: string;
|
|
49
|
+
playButtonTextKey: string;
|
|
50
|
+
style?: StyleProp<ViewStyle>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface TextToVoiceErrorMessageProps {
|
|
54
|
+
message: string;
|
|
55
|
+
style?: StyleProp<ViewStyle>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface TextToVoiceHeaderProps {
|
|
59
|
+
titleKey: string;
|
|
60
|
+
descriptionKey: string;
|
|
61
|
+
iconName: string;
|
|
62
|
+
navigationType?: "back" | "close";
|
|
63
|
+
headerContent?: ReactNode;
|
|
64
|
+
style?: StyleProp<ViewStyle>;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface TextToVoiceScreenConfig {
|
|
68
|
+
maxTextLength: number;
|
|
69
|
+
creditCost: number;
|
|
70
|
+
defaultModel?: string;
|
|
71
|
+
defaultVoice?: string;
|
|
72
|
+
defaultSpeed?: number;
|
|
73
|
+
defaultStability?: number;
|
|
74
|
+
defaultSimilarityBoost?: number;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface TextToVoiceTranslationKeys {
|
|
78
|
+
title: string;
|
|
79
|
+
description: string;
|
|
80
|
+
textInputLabel: string;
|
|
81
|
+
textInputPlaceholder: string;
|
|
82
|
+
characterCount: string;
|
|
83
|
+
voiceLabel: string;
|
|
84
|
+
voicePlaceholder: string;
|
|
85
|
+
voiceHint: string;
|
|
86
|
+
examplesLabel: string;
|
|
87
|
+
generateButton: string;
|
|
88
|
+
generatingText: string;
|
|
89
|
+
successText: string;
|
|
90
|
+
playButton: string;
|
|
91
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text-to-Voice Config Types
|
|
3
|
+
* Feature configuration types
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { TextToVoiceOptions, TextToVoiceResult } from "./generation.types";
|
|
7
|
+
|
|
8
|
+
export type TextToVoiceInputBuilder = (
|
|
9
|
+
text: string,
|
|
10
|
+
options?: TextToVoiceOptions,
|
|
11
|
+
) => Record<string, unknown>;
|
|
12
|
+
|
|
13
|
+
export type TextToVoiceResultExtractor = (
|
|
14
|
+
result: unknown,
|
|
15
|
+
) => { audioUrl?: string; duration?: number } | undefined;
|
|
16
|
+
|
|
17
|
+
export interface TextToVoiceFeatureConfig {
|
|
18
|
+
providerId?: string;
|
|
19
|
+
creditCost?: number;
|
|
20
|
+
model: string;
|
|
21
|
+
buildInput: TextToVoiceInputBuilder;
|
|
22
|
+
extractResult?: TextToVoiceResultExtractor;
|
|
23
|
+
onTextChange?: (text: string) => void;
|
|
24
|
+
onProcessingStart?: () => void;
|
|
25
|
+
onProcessingComplete?: (result: TextToVoiceResult) => void;
|
|
26
|
+
onError?: (error: string) => void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface TextToVoiceExecuteOptions {
|
|
30
|
+
model: string;
|
|
31
|
+
buildInput: TextToVoiceInputBuilder;
|
|
32
|
+
extractResult?: TextToVoiceResultExtractor;
|
|
33
|
+
onProgress?: (progress: number) => void;
|
|
34
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text-to-Voice Form Types
|
|
3
|
+
* Form state and setter types
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { TextToVoiceRequest } from "./generation.types";
|
|
7
|
+
|
|
8
|
+
export interface TextToVoiceFormState {
|
|
9
|
+
text: string;
|
|
10
|
+
model: string;
|
|
11
|
+
voice: string;
|
|
12
|
+
speed: number;
|
|
13
|
+
stability: number;
|
|
14
|
+
similarityBoost: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface TextToVoiceFormSetters {
|
|
18
|
+
setText: (text: string) => void;
|
|
19
|
+
setModel: (model: string) => void;
|
|
20
|
+
setVoice: (voice: string) => void;
|
|
21
|
+
setSpeed: (speed: number) => void;
|
|
22
|
+
setStability: (stability: number) => void;
|
|
23
|
+
setSimilarityBoost: (similarityBoost: number) => void;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface TextToVoiceFormReturn extends TextToVoiceFormSetters {
|
|
27
|
+
formState: TextToVoiceFormState;
|
|
28
|
+
buildRequest: () => TextToVoiceRequest;
|
|
29
|
+
resetForm: () => void;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface TextToVoiceFormConfig {
|
|
33
|
+
initialText?: string;
|
|
34
|
+
initialModel?: string;
|
|
35
|
+
initialVoice?: string;
|
|
36
|
+
initialSpeed?: number;
|
|
37
|
+
initialStability?: number;
|
|
38
|
+
initialSimilarityBoost?: number;
|
|
39
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text-to-Voice Generation Types
|
|
3
|
+
* Request, result, and state types for voice generation
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export interface TextToVoiceOptions {
|
|
7
|
+
voice?: string;
|
|
8
|
+
speed?: number;
|
|
9
|
+
pitch?: number;
|
|
10
|
+
stability?: number;
|
|
11
|
+
similarityBoost?: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export interface TextToVoiceRequest {
|
|
15
|
+
text: string;
|
|
16
|
+
userId: string;
|
|
17
|
+
model?: string;
|
|
18
|
+
options?: TextToVoiceOptions;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface TextToVoiceResult {
|
|
22
|
+
success: boolean;
|
|
23
|
+
audioUrl?: string;
|
|
24
|
+
error?: string;
|
|
25
|
+
requestId?: string;
|
|
26
|
+
duration?: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface TextToVoiceGenerationState {
|
|
30
|
+
isGenerating: boolean;
|
|
31
|
+
progress: number;
|
|
32
|
+
audioUrl: string | null;
|
|
33
|
+
error: string | null;
|
|
34
|
+
requestId: string | null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface VoiceGeneration {
|
|
38
|
+
id: string;
|
|
39
|
+
text: string;
|
|
40
|
+
audioUrl: string;
|
|
41
|
+
provider: string;
|
|
42
|
+
createdAt: string;
|
|
43
|
+
}
|
|
@@ -1,10 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text-to-Voice Domain Types
|
|
3
|
+
* Barrel export for all types
|
|
4
|
+
*/
|
|
5
|
+
|
|
1
6
|
export type {
|
|
2
7
|
TextToVoiceOptions,
|
|
3
8
|
TextToVoiceRequest,
|
|
4
9
|
TextToVoiceResult,
|
|
5
|
-
|
|
6
|
-
|
|
10
|
+
TextToVoiceGenerationState,
|
|
11
|
+
VoiceGeneration,
|
|
12
|
+
} from "./generation.types";
|
|
13
|
+
|
|
14
|
+
export type {
|
|
15
|
+
TextToVoiceFormState,
|
|
16
|
+
TextToVoiceFormSetters,
|
|
17
|
+
TextToVoiceFormReturn,
|
|
18
|
+
TextToVoiceFormConfig,
|
|
19
|
+
} from "./form.types";
|
|
20
|
+
|
|
21
|
+
export type {
|
|
22
|
+
TextToVoiceTextInputProps,
|
|
23
|
+
TextToVoiceOptionalInputProps,
|
|
24
|
+
TextToVoiceExamplePromptsProps,
|
|
25
|
+
TextToVoiceGenerateButtonProps,
|
|
26
|
+
TextToVoiceAudioPlayerProps,
|
|
27
|
+
TextToVoiceErrorMessageProps,
|
|
28
|
+
TextToVoiceHeaderProps,
|
|
29
|
+
TextToVoiceScreenConfig,
|
|
30
|
+
TextToVoiceTranslationKeys,
|
|
31
|
+
} from "./component.types";
|
|
32
|
+
|
|
33
|
+
export type {
|
|
7
34
|
TextToVoiceInputBuilder,
|
|
8
35
|
TextToVoiceResultExtractor,
|
|
9
36
|
TextToVoiceFeatureConfig,
|
|
10
|
-
|
|
37
|
+
TextToVoiceExecuteOptions,
|
|
38
|
+
} from "./config.types";
|
|
@@ -7,19 +7,11 @@ import { providerRegistry } from "../../../../infrastructure/services";
|
|
|
7
7
|
import type {
|
|
8
8
|
TextToVoiceRequest,
|
|
9
9
|
TextToVoiceResult,
|
|
10
|
-
|
|
11
|
-
TextToVoiceResultExtractor,
|
|
10
|
+
TextToVoiceExecuteOptions,
|
|
12
11
|
} from "../../domain/types";
|
|
13
12
|
|
|
14
13
|
declare const __DEV__: boolean;
|
|
15
14
|
|
|
16
|
-
export interface ExecuteTextToVoiceOptions {
|
|
17
|
-
model: string;
|
|
18
|
-
buildInput: TextToVoiceInputBuilder;
|
|
19
|
-
extractResult?: TextToVoiceResultExtractor;
|
|
20
|
-
onProgress?: (progress: number) => void;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
15
|
function defaultExtractResult(
|
|
24
16
|
result: unknown,
|
|
25
17
|
): { audioUrl?: string; duration?: number } | undefined {
|
|
@@ -50,7 +42,7 @@ function defaultExtractResult(
|
|
|
50
42
|
|
|
51
43
|
export async function executeTextToVoice(
|
|
52
44
|
request: TextToVoiceRequest,
|
|
53
|
-
options:
|
|
45
|
+
options: TextToVoiceExecuteOptions,
|
|
54
46
|
): Promise<TextToVoiceResult> {
|
|
55
47
|
const provider = providerRegistry.getActiveProvider();
|
|
56
48
|
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Text-to-Voice Feature Types
|
|
3
|
-
* Request, Result, Config types for text-to-voice generation
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
export interface TextToVoiceOptions {
|
|
7
|
-
voice?: string;
|
|
8
|
-
speed?: number;
|
|
9
|
-
pitch?: number;
|
|
10
|
-
stability?: number;
|
|
11
|
-
similarityBoost?: number;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface TextToVoiceRequest {
|
|
15
|
-
text: string;
|
|
16
|
-
userId: string;
|
|
17
|
-
options?: TextToVoiceOptions;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface TextToVoiceResult {
|
|
21
|
-
success: boolean;
|
|
22
|
-
audioUrl?: string;
|
|
23
|
-
error?: string;
|
|
24
|
-
requestId?: string;
|
|
25
|
-
duration?: number;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export interface TextToVoiceFeatureState {
|
|
29
|
-
text: string;
|
|
30
|
-
audioUrl: string | null;
|
|
31
|
-
isProcessing: boolean;
|
|
32
|
-
progress: number;
|
|
33
|
-
error: string | null;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export interface TextToVoiceTranslations {
|
|
37
|
-
textPlaceholder: string;
|
|
38
|
-
generateButtonText: string;
|
|
39
|
-
processingText: string;
|
|
40
|
-
successText: string;
|
|
41
|
-
playButtonText: string;
|
|
42
|
-
saveButtonText: string;
|
|
43
|
-
tryAnotherText: string;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export type TextToVoiceInputBuilder = (
|
|
47
|
-
text: string,
|
|
48
|
-
options?: TextToVoiceOptions,
|
|
49
|
-
) => Record<string, unknown>;
|
|
50
|
-
|
|
51
|
-
export type TextToVoiceResultExtractor = (
|
|
52
|
-
result: unknown,
|
|
53
|
-
) => { audioUrl?: string; duration?: number } | undefined;
|
|
54
|
-
|
|
55
|
-
export interface TextToVoiceFeatureConfig {
|
|
56
|
-
providerId?: string;
|
|
57
|
-
creditCost?: number;
|
|
58
|
-
model: string;
|
|
59
|
-
buildInput: TextToVoiceInputBuilder;
|
|
60
|
-
extractResult?: TextToVoiceResultExtractor;
|
|
61
|
-
onTextChange?: (text: string) => void;
|
|
62
|
-
onProcessingStart?: () => void;
|
|
63
|
-
onProcessingComplete?: (result: TextToVoiceResult) => void;
|
|
64
|
-
onError?: (error: string) => void;
|
|
65
|
-
}
|