@umituz/react-native-ai-generation-content 1.17.304 → 1.17.306
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 +3 -3
- package/src/features/couple-future/presentation/hooks/useCoupleFutureGeneration.ts +5 -0
- package/src/features/love-message/presentation/screens/LoveMessageExploreScreen.tsx +5 -4
- package/src/features/love-message/presentation/screens/LoveMessageGeneratorScreen.tsx +7 -5
- package/src/features/love-message/presentation/screens/MessageListScreen.tsx +5 -4
- package/src/features/love-message/presentation/screens/PartnerProfileScreen.tsx +4 -3
- package/src/infrastructure/services/generation-orchestrator.service.ts +5 -5
- package/src/infrastructure/services/image-feature-executor.service.ts +5 -5
- package/src/infrastructure/services/provider-registry.service.ts +6 -12
- package/src/infrastructure/utils/error-classifier.util.ts +2 -2
- package/src/infrastructure/utils/feature-utils.ts +7 -7
- package/src/infrastructure/utils/video-result-extractor.util.ts +5 -5
- package/src/presentation/components/AIGenerationForm.tsx +2 -4
- package/src/presentation/components/buttons/GenerateButton.tsx +3 -6
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.306",
|
|
4
4
|
"description": "Provider-agnostic AI generation orchestration for React Native with result preview components",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
],
|
|
18
18
|
"scripts": {
|
|
19
19
|
"typecheck": "tsc --noEmit --skipLibCheck",
|
|
20
|
-
"lint": "eslint src --
|
|
21
|
-
"lint:fix": "eslint src --
|
|
20
|
+
"lint": "eslint src --max-warnings 0",
|
|
21
|
+
"lint:fix": "eslint src --fix"
|
|
22
22
|
},
|
|
23
23
|
"keywords": [
|
|
24
24
|
"react-native",
|
|
@@ -10,6 +10,9 @@ export interface UseCoupleFutureGenerationConfig<TInput extends CoupleFutureInpu
|
|
|
10
10
|
userId: string | undefined;
|
|
11
11
|
processResult: (imageUrl: string, input: TInput) => Promise<TResult> | TResult;
|
|
12
12
|
buildCreation?: (result: TResult, input: TInput) => Creation | null;
|
|
13
|
+
/** Check credits BEFORE generation starts - critical for security */
|
|
14
|
+
checkCredits?: () => Promise<boolean>;
|
|
15
|
+
/** Deduct credits AFTER successful generation */
|
|
13
16
|
deductCredits?: () => Promise<void>;
|
|
14
17
|
onSuccess?: (result: TResult) => void;
|
|
15
18
|
onError?: (error: string) => void;
|
|
@@ -29,6 +32,7 @@ export const useCoupleFutureGeneration = <TInput extends CoupleFutureInput, TRes
|
|
|
29
32
|
userId,
|
|
30
33
|
processResult,
|
|
31
34
|
buildCreation,
|
|
35
|
+
checkCredits,
|
|
32
36
|
deductCredits,
|
|
33
37
|
onSuccess,
|
|
34
38
|
onError,
|
|
@@ -65,6 +69,7 @@ export const useCoupleFutureGeneration = <TInput extends CoupleFutureInput, TRes
|
|
|
65
69
|
}
|
|
66
70
|
},
|
|
67
71
|
|
|
72
|
+
checkCredits,
|
|
68
73
|
deductCredits,
|
|
69
74
|
onSuccess,
|
|
70
75
|
onError: (error: PhotoGenerationError) => {
|
|
@@ -8,7 +8,7 @@ import { View, ScrollView, StyleSheet } from "react-native";
|
|
|
8
8
|
import {
|
|
9
9
|
useAppDesignTokens,
|
|
10
10
|
useSafeAreaInsets,
|
|
11
|
-
|
|
11
|
+
useAppNavigation,
|
|
12
12
|
} from "@umituz/react-native-design-system";
|
|
13
13
|
import { ExploreHeader } from "../components/ExploreHeader";
|
|
14
14
|
import { LoveMessageHeroSection } from "../components/LoveMessageHeroSection";
|
|
@@ -18,17 +18,18 @@ import { TrendingSection } from "../components/TrendingSection";
|
|
|
18
18
|
export const LoveMessageExploreScreen: FC = () => {
|
|
19
19
|
const tokens = useAppDesignTokens();
|
|
20
20
|
const { bottom } = useSafeAreaInsets();
|
|
21
|
+
const navigation = useAppNavigation();
|
|
21
22
|
|
|
22
23
|
const handleNavigateToGenerator = () => {
|
|
23
|
-
|
|
24
|
+
navigation.navigate("MessageGenerator", {});
|
|
24
25
|
};
|
|
25
26
|
|
|
26
27
|
const handleNavigateToCategory = (categoryId: string) => {
|
|
27
|
-
|
|
28
|
+
navigation.navigate("MessageList", { categoryId });
|
|
28
29
|
};
|
|
29
30
|
|
|
30
31
|
const handleNavigateToTrending = () => {
|
|
31
|
-
|
|
32
|
+
navigation.navigate("MessageList", { categoryId: "trending" });
|
|
32
33
|
};
|
|
33
34
|
|
|
34
35
|
return (
|
|
@@ -8,12 +8,13 @@ import { View, ScrollView, StyleSheet, Animated } from "react-native";
|
|
|
8
8
|
import {
|
|
9
9
|
AtomicText,
|
|
10
10
|
AtomicButton,
|
|
11
|
-
|
|
12
|
-
useSafeAreaInsets,
|
|
13
|
-
AppNavigation,
|
|
11
|
+
useAppNavigation,
|
|
14
12
|
useAppRoute,
|
|
15
13
|
AlertService,
|
|
14
|
+
useAppDesignTokens,
|
|
15
|
+
useSafeAreaInsets,
|
|
16
16
|
} from "@umituz/react-native-design-system";
|
|
17
|
+
|
|
17
18
|
import { useLocalization } from "@umituz/react-native-localization";
|
|
18
19
|
import { ProgressDots } from "../components/ProgressDots";
|
|
19
20
|
import { MessageResult } from "../components/MessageResult";
|
|
@@ -30,6 +31,7 @@ export const LoveMessageGeneratorScreen: FC = () => {
|
|
|
30
31
|
const tokens = useAppDesignTokens();
|
|
31
32
|
const { bottom } = useSafeAreaInsets();
|
|
32
33
|
const { t } = useLocalization();
|
|
34
|
+
const navigation = useAppNavigation();
|
|
33
35
|
const route = useAppRoute<{ params: RouteParams }, "params">();
|
|
34
36
|
|
|
35
37
|
const initialType = route.params?.initialType;
|
|
@@ -49,13 +51,13 @@ export const LoveMessageGeneratorScreen: FC = () => {
|
|
|
49
51
|
}, [t]);
|
|
50
52
|
|
|
51
53
|
const gen = useLoveMessageGenerator({
|
|
52
|
-
onBack: () =>
|
|
54
|
+
onBack: () => navigation.goBack(),
|
|
53
55
|
initialType,
|
|
54
56
|
onSuccess: handleSuccess,
|
|
55
57
|
onError: handleError,
|
|
56
58
|
});
|
|
57
59
|
|
|
58
|
-
const handleNavigateToProfile = () =>
|
|
60
|
+
const handleNavigateToProfile = () => navigation.navigate("PartnerProfile");
|
|
59
61
|
|
|
60
62
|
const stepTitle = useMemo(() => {
|
|
61
63
|
switch (gen.currentStep) {
|
|
@@ -7,10 +7,10 @@ import { View, ScrollView, StyleSheet, Pressable, Share } from "react-native";
|
|
|
7
7
|
import {
|
|
8
8
|
AtomicText,
|
|
9
9
|
AtomicIcon,
|
|
10
|
+
useAppNavigation,
|
|
11
|
+
useAppRoute,
|
|
10
12
|
useAppDesignTokens,
|
|
11
13
|
useSafeAreaInsets,
|
|
12
|
-
AppNavigation,
|
|
13
|
-
useAppRoute,
|
|
14
14
|
} from "@umituz/react-native-design-system";
|
|
15
15
|
import { useLocalization } from "@umituz/react-native-localization";
|
|
16
16
|
import { CATEGORY_TEMPLATES, MESSAGE_TYPES } from "../../domain/constants";
|
|
@@ -23,6 +23,7 @@ export const MessageListScreen: FC = () => {
|
|
|
23
23
|
const tokens = useAppDesignTokens();
|
|
24
24
|
const { top, bottom } = useSafeAreaInsets();
|
|
25
25
|
const { t } = useLocalization();
|
|
26
|
+
const navigation = useAppNavigation();
|
|
26
27
|
const route = useAppRoute<{ params: RouteParams }, "params">();
|
|
27
28
|
|
|
28
29
|
const categoryId = route.params?.categoryId ?? "romantic";
|
|
@@ -34,10 +35,10 @@ export const MessageListScreen: FC = () => {
|
|
|
34
35
|
return config ? t(config.labelKey) : categoryId;
|
|
35
36
|
}, [categoryId, t]);
|
|
36
37
|
|
|
37
|
-
const handleBack = () =>
|
|
38
|
+
const handleBack = () => navigation.goBack();
|
|
38
39
|
|
|
39
40
|
const handleNavigateToGenerator = (type?: string) => {
|
|
40
|
-
|
|
41
|
+
navigation.navigate("MessageGenerator", { initialType: type as MessageType });
|
|
41
42
|
};
|
|
42
43
|
|
|
43
44
|
const handleShare = useCallback(async (text: string) => {
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
AtomicButton,
|
|
10
10
|
useAppDesignTokens,
|
|
11
11
|
useSafeAreaInsets,
|
|
12
|
-
|
|
12
|
+
useAppNavigation,
|
|
13
13
|
} from "@umituz/react-native-design-system";
|
|
14
14
|
import { useLocalization } from "@umituz/react-native-localization";
|
|
15
15
|
import { LOVE_LANGUAGES } from "../../domain/constants";
|
|
@@ -20,14 +20,15 @@ export const PartnerProfileScreen: FC = () => {
|
|
|
20
20
|
const tokens = useAppDesignTokens();
|
|
21
21
|
const { top, bottom } = useSafeAreaInsets();
|
|
22
22
|
const { t } = useLocalization();
|
|
23
|
-
const
|
|
23
|
+
const navigation = useAppNavigation();
|
|
24
|
+
const p = usePartnerProfile(() => navigation.goBack());
|
|
24
25
|
|
|
25
26
|
if (p.isLoading) return null;
|
|
26
27
|
|
|
27
28
|
return (
|
|
28
29
|
<View style={[styles.container, { backgroundColor: tokens.colors.backgroundPrimary }]}>
|
|
29
30
|
<View style={[styles.header, { paddingTop: top + tokens.spacing.md }]}>
|
|
30
|
-
<AtomicButton icon="arrow-back" onPress={() =>
|
|
31
|
+
<AtomicButton icon="arrow-back" onPress={() => navigation.goBack()} variant="text" size="sm" />
|
|
31
32
|
<View style={styles.headerTitle}>
|
|
32
33
|
<AtomicText type="headlineSmall" color="textPrimary" style={styles.headerText}>
|
|
33
34
|
{t("loveMessage.partnerProfile.title")}
|
|
@@ -28,7 +28,7 @@ class GenerationOrchestratorService {
|
|
|
28
28
|
private onStatusUpdateCallback?: (requestId: string, status: string) => Promise<void>;
|
|
29
29
|
|
|
30
30
|
configure(config: OrchestratorConfig): void {
|
|
31
|
-
if (
|
|
31
|
+
if (__DEV__) {
|
|
32
32
|
console.log("[Orchestrator] configure() called", {
|
|
33
33
|
hasPollingConfig: !!config.polling,
|
|
34
34
|
hasStatusUpdate: !!config.onStatusUpdate,
|
|
@@ -45,7 +45,7 @@ class GenerationOrchestratorService {
|
|
|
45
45
|
const provider = this.providerValidator.getProvider();
|
|
46
46
|
const startTime = Date.now();
|
|
47
47
|
|
|
48
|
-
if (
|
|
48
|
+
if (__DEV__) {
|
|
49
49
|
console.log("[Orchestrator] Generate started:", {
|
|
50
50
|
model: request.model,
|
|
51
51
|
capability: request.capability,
|
|
@@ -67,7 +67,7 @@ class GenerationOrchestratorService {
|
|
|
67
67
|
|
|
68
68
|
updateProgress("submitting");
|
|
69
69
|
|
|
70
|
-
if (
|
|
70
|
+
if (__DEV__) {
|
|
71
71
|
console.log("[Orchestrator] Job submitted:", {
|
|
72
72
|
requestId: submission.requestId,
|
|
73
73
|
provider: provider.providerId,
|
|
@@ -113,7 +113,7 @@ class GenerationOrchestratorService {
|
|
|
113
113
|
|
|
114
114
|
const duration = Date.now() - startTime;
|
|
115
115
|
|
|
116
|
-
if (
|
|
116
|
+
if (__DEV__) {
|
|
117
117
|
console.log("[Orchestrator] Generate completed:", {
|
|
118
118
|
requestId: submission.requestId,
|
|
119
119
|
duration: `${duration}ms`,
|
|
@@ -137,7 +137,7 @@ class GenerationOrchestratorService {
|
|
|
137
137
|
} catch (error) {
|
|
138
138
|
const errorInfo = classifyError(error);
|
|
139
139
|
|
|
140
|
-
if (
|
|
140
|
+
if (__DEV__) {
|
|
141
141
|
console.error("[Orchestrator] Generation failed:", errorInfo);
|
|
142
142
|
}
|
|
143
143
|
|
|
@@ -52,7 +52,7 @@ function defaultExtractImageResult(result: unknown): string | undefined {
|
|
|
52
52
|
|
|
53
53
|
const r = result as Record<string, unknown>;
|
|
54
54
|
|
|
55
|
-
if (
|
|
55
|
+
if (__DEV__) {
|
|
56
56
|
console.log("[ImageExtractor] Result keys:", Object.keys(r));
|
|
57
57
|
console.log("[ImageExtractor] Has data:", !!r.data);
|
|
58
58
|
console.log("[ImageExtractor] Has images:", !!r.images);
|
|
@@ -61,7 +61,7 @@ function defaultExtractImageResult(result: unknown): string | undefined {
|
|
|
61
61
|
// Handle fal.ai data wrapper
|
|
62
62
|
const data = (r.data as Record<string, unknown>) ?? r;
|
|
63
63
|
|
|
64
|
-
if (
|
|
64
|
+
if (__DEV__) {
|
|
65
65
|
console.log("[ImageExtractor] Data keys:", Object.keys(data));
|
|
66
66
|
}
|
|
67
67
|
|
|
@@ -73,7 +73,7 @@ function defaultExtractImageResult(result: unknown): string | undefined {
|
|
|
73
73
|
// Object with url property (birefnet, rembg format: data.image.url)
|
|
74
74
|
const imageObj = data.image as Record<string, unknown> | undefined;
|
|
75
75
|
if (imageObj && typeof imageObj === "object" && typeof imageObj.url === "string") {
|
|
76
|
-
if (
|
|
76
|
+
if (__DEV__) {
|
|
77
77
|
console.log("[ImageExtractor] Found data.image.url:", imageObj.url);
|
|
78
78
|
}
|
|
79
79
|
return imageObj.url;
|
|
@@ -81,13 +81,13 @@ function defaultExtractImageResult(result: unknown): string | undefined {
|
|
|
81
81
|
|
|
82
82
|
// Array format (flux, etc: data.images[0].url)
|
|
83
83
|
if (Array.isArray(data.images) && typeof data.images[0]?.url === "string") {
|
|
84
|
-
if (
|
|
84
|
+
if (__DEV__) {
|
|
85
85
|
console.log("[ImageExtractor] Found images[0].url:", data.images[0].url);
|
|
86
86
|
}
|
|
87
87
|
return data.images[0].url;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
if (
|
|
90
|
+
if (__DEV__) {
|
|
91
91
|
console.log("[ImageExtractor] No image URL found in result");
|
|
92
92
|
}
|
|
93
93
|
|
|
@@ -13,8 +13,7 @@ class ProviderRegistry {
|
|
|
13
13
|
|
|
14
14
|
register(provider: IAIProvider): void {
|
|
15
15
|
if (this.providers.has(provider.providerId)) {
|
|
16
|
-
if (
|
|
17
|
-
|
|
16
|
+
if (__DEV__) {
|
|
18
17
|
console.warn(
|
|
19
18
|
`[ProviderRegistry] Provider ${provider.providerId} already registered`,
|
|
20
19
|
);
|
|
@@ -24,8 +23,7 @@ class ProviderRegistry {
|
|
|
24
23
|
|
|
25
24
|
this.providers.set(provider.providerId, provider);
|
|
26
25
|
|
|
27
|
-
if (
|
|
28
|
-
|
|
26
|
+
if (__DEV__) {
|
|
29
27
|
console.log(
|
|
30
28
|
`[ProviderRegistry] Registered provider: ${provider.providerId}`,
|
|
31
29
|
);
|
|
@@ -45,15 +43,13 @@ class ProviderRegistry {
|
|
|
45
43
|
}
|
|
46
44
|
this.activeProviderId = providerId;
|
|
47
45
|
|
|
48
|
-
if (
|
|
49
|
-
|
|
46
|
+
if (__DEV__) {
|
|
50
47
|
console.log(`[ProviderRegistry] Active provider set to: ${providerId}`);
|
|
51
48
|
}
|
|
52
49
|
}
|
|
53
50
|
|
|
54
51
|
getActiveProvider(): IAIProvider | null {
|
|
55
|
-
if (
|
|
56
|
-
|
|
52
|
+
if (__DEV__) {
|
|
57
53
|
console.log("[ProviderRegistry] getActiveProvider() called", {
|
|
58
54
|
activeProviderId: this.activeProviderId,
|
|
59
55
|
registeredProviders: Array.from(this.providers.keys()),
|
|
@@ -61,8 +57,7 @@ class ProviderRegistry {
|
|
|
61
57
|
}
|
|
62
58
|
|
|
63
59
|
if (!this.activeProviderId) {
|
|
64
|
-
if (
|
|
65
|
-
|
|
60
|
+
if (__DEV__) {
|
|
66
61
|
console.warn("[ProviderRegistry] No active provider set!");
|
|
67
62
|
}
|
|
68
63
|
return null;
|
|
@@ -70,8 +65,7 @@ class ProviderRegistry {
|
|
|
70
65
|
|
|
71
66
|
const provider = this.providers.get(this.activeProviderId) ?? null;
|
|
72
67
|
|
|
73
|
-
if (
|
|
74
|
-
|
|
68
|
+
if (__DEV__) {
|
|
75
69
|
console.log("[ProviderRegistry] getActiveProvider() returning", {
|
|
76
70
|
providerId: provider?.providerId,
|
|
77
71
|
isInitialized: provider?.isInitialized(),
|
|
@@ -33,7 +33,7 @@ function getStatusCode(error: unknown): number | undefined {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
function logClassification(info: AIErrorInfo): AIErrorInfo {
|
|
36
|
-
if (
|
|
36
|
+
if (__DEV__) {
|
|
37
37
|
console.log("[ErrorClassifier] Classified as:", {
|
|
38
38
|
type: info.type,
|
|
39
39
|
messageKey: info.messageKey,
|
|
@@ -47,7 +47,7 @@ export function classifyError(error: unknown): AIErrorInfo {
|
|
|
47
47
|
const message = error instanceof Error ? error.message : String(error);
|
|
48
48
|
const statusCode = getStatusCode(error);
|
|
49
49
|
|
|
50
|
-
if (
|
|
50
|
+
if (__DEV__) {
|
|
51
51
|
console.log("[ErrorClassifier] Classifying error:", {
|
|
52
52
|
message: message.slice(0, 100),
|
|
53
53
|
statusCode,
|
|
@@ -23,7 +23,7 @@ export interface FeatureUtilsConfig {
|
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
export async function prepareImage(uri: string): Promise<string> {
|
|
26
|
-
if (
|
|
26
|
+
if (__DEV__) {
|
|
27
27
|
console.log("[prepareImage] Starting with URI:", uri);
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -34,7 +34,7 @@ export async function prepareImage(uri: string): Promise<string> {
|
|
|
34
34
|
try {
|
|
35
35
|
const base64 = await readFileAsBase64(uri);
|
|
36
36
|
|
|
37
|
-
if (
|
|
37
|
+
if (__DEV__) {
|
|
38
38
|
console.log("[prepareImage] Base64 length:", base64?.length || 0);
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -45,7 +45,7 @@ export async function prepareImage(uri: string): Promise<string> {
|
|
|
45
45
|
return base64;
|
|
46
46
|
} catch (error) {
|
|
47
47
|
const message = error instanceof Error ? error.message : String(error);
|
|
48
|
-
if (
|
|
48
|
+
if (__DEV__) {
|
|
49
49
|
console.error("[prepareImage] Error:", message);
|
|
50
50
|
}
|
|
51
51
|
throw new Error(`[prepareImage] Failed: ${message}`);
|
|
@@ -55,13 +55,13 @@ export async function prepareImage(uri: string): Promise<string> {
|
|
|
55
55
|
export function createDevCallbacks(featureName: string) {
|
|
56
56
|
return {
|
|
57
57
|
onSuccess: (result: unknown) => {
|
|
58
|
-
if (
|
|
58
|
+
if (__DEV__) {
|
|
59
59
|
|
|
60
60
|
console.log(`[${featureName}] Success:`, result);
|
|
61
61
|
}
|
|
62
62
|
},
|
|
63
63
|
onError: (error: unknown) => {
|
|
64
|
-
if (
|
|
64
|
+
if (__DEV__) {
|
|
65
65
|
|
|
66
66
|
console.error(`[${featureName}] Error:`, error);
|
|
67
67
|
}
|
|
@@ -82,7 +82,7 @@ async function checkCreditGuard(cost: number, featureName: string): Promise<bool
|
|
|
82
82
|
const paywallService = getPaywallService();
|
|
83
83
|
|
|
84
84
|
if (!authService.isAuthenticated()) {
|
|
85
|
-
if (
|
|
85
|
+
if (__DEV__) {
|
|
86
86
|
|
|
87
87
|
console.log(`[${featureName}] Auth required`);
|
|
88
88
|
}
|
|
@@ -96,7 +96,7 @@ async function checkCreditGuard(cost: number, featureName: string): Promise<bool
|
|
|
96
96
|
|
|
97
97
|
const hasCredits = await creditService.checkCredits(cost);
|
|
98
98
|
if (!hasCredits) {
|
|
99
|
-
if (
|
|
99
|
+
if (__DEV__) {
|
|
100
100
|
|
|
101
101
|
console.log(`[${featureName}] Insufficient credits`);
|
|
102
102
|
}
|
|
@@ -16,14 +16,14 @@ export const defaultExtractVideoResult: VideoResultExtractor = (result) => {
|
|
|
16
16
|
|
|
17
17
|
const r = result as Record<string, unknown>;
|
|
18
18
|
|
|
19
|
-
if (
|
|
19
|
+
if (__DEV__) {
|
|
20
20
|
console.log("[VideoExtractor] Result keys:", Object.keys(r));
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
// Handle fal.ai data wrapper
|
|
24
24
|
const data = (r.data as Record<string, unknown>) ?? r;
|
|
25
25
|
|
|
26
|
-
if (
|
|
26
|
+
if (__DEV__) {
|
|
27
27
|
console.log("[VideoExtractor] Data keys:", Object.keys(data));
|
|
28
28
|
}
|
|
29
29
|
|
|
@@ -37,7 +37,7 @@ export const defaultExtractVideoResult: VideoResultExtractor = (result) => {
|
|
|
37
37
|
// Object with url property (e.g., { video: { url: "..." } })
|
|
38
38
|
const videoObj = data.video as Record<string, unknown> | undefined;
|
|
39
39
|
if (videoObj && typeof videoObj === "object" && typeof videoObj.url === "string") {
|
|
40
|
-
if (
|
|
40
|
+
if (__DEV__) {
|
|
41
41
|
console.log("[VideoExtractor] Found data.video.url:", videoObj.url);
|
|
42
42
|
}
|
|
43
43
|
return videoObj.url;
|
|
@@ -45,13 +45,13 @@ export const defaultExtractVideoResult: VideoResultExtractor = (result) => {
|
|
|
45
45
|
|
|
46
46
|
// Array format (e.g., { videos: [{ url: "..." }] })
|
|
47
47
|
if (Array.isArray(data.videos) && typeof data.videos[0]?.url === "string") {
|
|
48
|
-
if (
|
|
48
|
+
if (__DEV__) {
|
|
49
49
|
console.log("[VideoExtractor] Found videos[0].url:", data.videos[0].url);
|
|
50
50
|
}
|
|
51
51
|
return data.videos[0].url;
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
if (
|
|
54
|
+
if (__DEV__) {
|
|
55
55
|
console.log("[VideoExtractor] No video URL found in result");
|
|
56
56
|
}
|
|
57
57
|
|
|
@@ -47,8 +47,7 @@ export const AIGenerationForm: React.FC<AIGenerationFormProps> = ({
|
|
|
47
47
|
translations,
|
|
48
48
|
children,
|
|
49
49
|
}) => {
|
|
50
|
-
if (
|
|
51
|
-
|
|
50
|
+
if (__DEV__) {
|
|
52
51
|
console.log("[AIGenerationForm] RENDERING NOW - hideGenerateButton:", hideGenerateButton);
|
|
53
52
|
}
|
|
54
53
|
|
|
@@ -57,8 +56,7 @@ export const AIGenerationForm: React.FC<AIGenerationFormProps> = ({
|
|
|
57
56
|
const buttonIsDisabled = onPromptChange ? !prompt?.trim() : false;
|
|
58
57
|
|
|
59
58
|
useEffect(() => {
|
|
60
|
-
if (
|
|
61
|
-
|
|
59
|
+
if (__DEV__) {
|
|
62
60
|
console.log("[AIGenerationForm] MOUNTED/UPDATED - prompt:", prompt, "isGenerating:", isGenerating, "buttonIsDisabled:", buttonIsDisabled, "hideGenerateButton:", hideGenerateButton);
|
|
63
61
|
}
|
|
64
62
|
}, [prompt, isGenerating, buttonIsDisabled, hideGenerateButton]);
|
|
@@ -42,8 +42,7 @@ export const GenerateButton: React.FC<GenerateButtonProps> = ({
|
|
|
42
42
|
onAccessoryRightPress,
|
|
43
43
|
style,
|
|
44
44
|
}) => {
|
|
45
|
-
if (
|
|
46
|
-
|
|
45
|
+
if (__DEV__) {
|
|
47
46
|
console.log("[GenerateButton] RENDERING NOW");
|
|
48
47
|
}
|
|
49
48
|
|
|
@@ -53,15 +52,13 @@ export const GenerateButton: React.FC<GenerateButtonProps> = ({
|
|
|
53
52
|
const finalDisplayText = costLabel ? `${displayText} (${costLabel})` : displayText;
|
|
54
53
|
|
|
55
54
|
useEffect(() => {
|
|
56
|
-
if (
|
|
57
|
-
|
|
55
|
+
if (__DEV__) {
|
|
58
56
|
console.log("[GenerateButton] MOUNTED/UPDATED - isDisabled:", isDisabled, "isProcessing:", isProcessing, "disabled:", disabled, "text:", text);
|
|
59
57
|
}
|
|
60
58
|
}, [isDisabled, isProcessing, disabled, text]);
|
|
61
59
|
|
|
62
60
|
const handlePress = () => {
|
|
63
|
-
if (
|
|
64
|
-
|
|
61
|
+
if (__DEV__) {
|
|
65
62
|
console.log("[GenerateButton] PRESSED - disabled:", disabled, "isDisabled:", isDisabled, "isProcessing:", isProcessing);
|
|
66
63
|
}
|
|
67
64
|
if (!disabled) {
|