@umituz/react-native-ai-generation-content 1.17.277 → 1.17.278

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.277",
3
+ "version": "1.17.278",
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",
@@ -8,8 +8,8 @@ import {
8
8
  useSharing,
9
9
  FilterSheet,
10
10
  ScreenLayout,
11
+ useAppFocusEffect,
11
12
  } from "@umituz/react-native-design-system";
12
- import { useFocusEffect } from "@react-navigation/native";
13
13
  import { useCreations } from "../hooks/useCreations";
14
14
  import { useDeleteCreation } from "../hooks/useDeleteCreation";
15
15
  import { useGalleryFilters } from "../hooks/useGalleryFilters";
@@ -64,7 +64,7 @@ export function CreationsGalleryScreen({
64
64
 
65
65
  const filters = useGalleryFilters({ creations, statusOptions, mediaOptions, t });
66
66
 
67
- useFocusEffect(useCallback(() => { void refetch(); }, [refetch]));
67
+ useAppFocusEffect(useCallback(() => { void refetch(); }, [refetch]));
68
68
 
69
69
  const handleShareCard = useCallback((c: Creation) => {
70
70
  void share(c.uri, { dialogTitle: t("common.share") });
@@ -177,14 +177,17 @@ export function CreationsGalleryScreen({
177
177
  onShare={handleShare}
178
178
  onTryAgain={handleTryAgain}
179
179
  onNavigateBack={handleBack}
180
+ hideLabel
181
+ iconOnly
182
+ showTryAgain={false}
180
183
  translations={{
181
- title: t(config.translations.resultTitle ?? "result.title"),
182
- yourResult: t(config.translations.resultLabel ?? "result.yourResult"),
184
+ title: t(config.translations.title),
185
+ yourResult: "",
183
186
  saveButton: t("result.saveButton"),
184
187
  saving: t("result.saving"),
185
188
  shareButton: t("result.shareButton"),
186
189
  sharing: t("result.sharing"),
187
- tryAnother: t("result.tryAnother"),
190
+ tryAnother: "",
188
191
  }}
189
192
  />
190
193
  );
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * ResultActionBar Component
3
- * Action buttons for save, share, retry, and rate
3
+ * Action buttons for save, share, retry
4
4
  */
5
5
 
6
6
  import React, { useMemo } from "react";
@@ -21,6 +21,8 @@ export const ResultActionBar: React.FC<ResultActionBarProps> = ({
21
21
  saveButtonText,
22
22
  shareButtonText,
23
23
  tryAgainButtonText,
24
+ iconOnly = false,
25
+ showTryAgain = true,
24
26
  }) => {
25
27
  const tokens = useAppDesignTokens();
26
28
 
@@ -46,15 +48,57 @@ export const ResultActionBar: React.FC<ResultActionBarProps> = ({
46
48
  minWidth: 110,
47
49
  backgroundColor: tokens.colors.primary,
48
50
  },
51
+ iconButton: {
52
+ width: 56,
53
+ height: 56,
54
+ borderRadius: 28,
55
+ backgroundColor: tokens.colors.primary,
56
+ justifyContent: "center",
57
+ alignItems: "center",
58
+ },
49
59
  buttonText: {
50
60
  fontWeight: "700",
51
61
  color: tokens.colors.textInverse,
52
62
  fontSize: 15,
53
63
  },
64
+ disabledButton: {
65
+ opacity: 0.6,
66
+ },
54
67
  }),
55
68
  [tokens],
56
69
  );
57
70
 
71
+ if (iconOnly) {
72
+ return (
73
+ <View style={styles.container}>
74
+ <TouchableOpacity
75
+ style={[styles.iconButton, isSaving && styles.disabledButton]}
76
+ onPress={onDownload}
77
+ disabled={isSaving}
78
+ activeOpacity={0.7}
79
+ >
80
+ {isSaving ? (
81
+ <ActivityIndicator color={tokens.colors.textInverse} size="small" />
82
+ ) : (
83
+ <AtomicIcon name="download" customSize={24} color="onPrimary" />
84
+ )}
85
+ </TouchableOpacity>
86
+ <TouchableOpacity
87
+ style={[styles.iconButton, isSharing && styles.disabledButton]}
88
+ onPress={onShare}
89
+ disabled={isSharing}
90
+ activeOpacity={0.7}
91
+ >
92
+ {isSharing ? (
93
+ <ActivityIndicator color={tokens.colors.textInverse} size="small" />
94
+ ) : (
95
+ <AtomicIcon name="share-2" customSize={24} color="onPrimary" />
96
+ )}
97
+ </TouchableOpacity>
98
+ </View>
99
+ );
100
+ }
101
+
58
102
  return (
59
103
  <View style={styles.container}>
60
104
  <TouchableOpacity
@@ -66,11 +110,10 @@ export const ResultActionBar: React.FC<ResultActionBarProps> = ({
66
110
  {isSaving ? (
67
111
  <ActivityIndicator color={tokens.colors.textInverse} size="small" />
68
112
  ) : (
69
- <AtomicIcon name="download-outline" size="sm" color="onPrimary" />
113
+ <AtomicIcon name="download" customSize={18} color="onPrimary" />
70
114
  )}
71
115
  <AtomicText style={styles.buttonText}>{saveButtonText}</AtomicText>
72
116
  </TouchableOpacity>
73
-
74
117
  <TouchableOpacity
75
118
  style={styles.button}
76
119
  onPress={onShare}
@@ -80,19 +123,16 @@ export const ResultActionBar: React.FC<ResultActionBarProps> = ({
80
123
  {isSharing ? (
81
124
  <ActivityIndicator color={tokens.colors.textInverse} size="small" />
82
125
  ) : (
83
- <AtomicIcon name="share-social-outline" size="sm" color="onPrimary" />
126
+ <AtomicIcon name="share-2" customSize={18} color="onPrimary" />
84
127
  )}
85
128
  <AtomicText style={styles.buttonText}>{shareButtonText}</AtomicText>
86
129
  </TouchableOpacity>
87
-
88
- <TouchableOpacity
89
- style={styles.button}
90
- onPress={onTryAgain}
91
- activeOpacity={0.7}
92
- >
93
- <AtomicIcon name="refresh-outline" size="sm" color="onPrimary" />
94
- <AtomicText style={styles.buttonText}>{tryAgainButtonText}</AtomicText>
95
- </TouchableOpacity>
130
+ {showTryAgain && (
131
+ <TouchableOpacity style={styles.button} onPress={onTryAgain} activeOpacity={0.7}>
132
+ <AtomicIcon name="refresh-cw" customSize={18} color="onPrimary" />
133
+ <AtomicText style={styles.buttonText}>{tryAgainButtonText}</AtomicText>
134
+ </TouchableOpacity>
135
+ )}
96
136
  </View>
97
137
  );
98
138
  };
@@ -24,12 +24,14 @@ export const ResultPreviewScreen: React.FC<ResultPreviewScreenProps> = ({
24
24
  onShare,
25
25
  onTryAgain,
26
26
  onNavigateBack,
27
- _onRate,
28
27
  recentCreations,
29
28
  onViewAll,
30
29
  onCreationPress,
31
30
  translations,
32
31
  style,
32
+ hideLabel = false,
33
+ iconOnly = false,
34
+ showTryAgain = true,
33
35
  }) => {
34
36
  const tokens = useAppDesignTokens();
35
37
 
@@ -55,37 +57,22 @@ export const ResultPreviewScreen: React.FC<ResultPreviewScreenProps> = ({
55
57
 
56
58
  const displayImageUrl = useMemo(() => {
57
59
  if (!imageUrl) return null;
58
-
59
- // If not a URL and not a data URL, assume it's base64
60
- if (
61
- !imageUrl.startsWith("http") &&
62
- !imageUrl.startsWith("data:image")
63
- ) {
60
+ if (!imageUrl.startsWith("http") && !imageUrl.startsWith("data:image")) {
64
61
  return `data:image/jpeg;base64,${imageUrl}`;
65
62
  }
66
-
67
63
  return imageUrl;
68
64
  }, [imageUrl]);
69
65
 
70
- if (!displayImageUrl) {
71
- return null;
72
- }
66
+ if (!displayImageUrl) return null;
73
67
 
74
68
  return (
75
- <ScreenLayout
76
- scrollable
77
- edges={["left", "right"]}
78
- backgroundColor={tokens.colors.backgroundPrimary}
79
- >
80
- <NavigationHeader
81
- title={translations.title}
82
- onBackPress={onNavigateBack}
83
- />
69
+ <ScreenLayout scrollable edges={["left", "right"]} backgroundColor={tokens.colors.backgroundPrimary}>
70
+ <NavigationHeader title={translations.title} onBackPress={onNavigateBack} />
84
71
  <View style={[styles.container, style]}>
85
72
  <View style={styles.resultContainer}>
86
- <AtomicText style={styles.title}>
87
- {translations.yourResult}
88
- </AtomicText>
73
+ {!hideLabel && (
74
+ <AtomicText style={styles.title}>{translations.yourResult}</AtomicText>
75
+ )}
89
76
  <ResultImageCard imageUrl={displayImageUrl} />
90
77
  <ResultActionBar
91
78
  isSaving={isSaving}
@@ -96,6 +83,8 @@ export const ResultPreviewScreen: React.FC<ResultPreviewScreenProps> = ({
96
83
  saveButtonText={translations.saveButton}
97
84
  shareButtonText={translations.shareButton}
98
85
  tryAgainButtonText={translations.tryAnother}
86
+ iconOnly={iconOnly}
87
+ showTryAgain={showTryAgain}
99
88
  />
100
89
  </View>
101
90
  {recentCreations && recentCreations.length > 0 && translations.recentCreations && translations.viewAll && (
@@ -69,6 +69,10 @@ export interface ResultActionBarProps {
69
69
  shareButtonText: string;
70
70
  /** Try again button text */
71
71
  tryAgainButtonText: string;
72
+ /** Show only icons without text */
73
+ iconOnly?: boolean;
74
+ /** Show try again button */
75
+ showTryAgain?: boolean;
72
76
  }
73
77
 
74
78
  /**
@@ -107,6 +111,12 @@ export interface ResultPreviewScreenProps {
107
111
  translations: ResultPreviewTranslations;
108
112
  /** Optional custom style */
109
113
  style?: StyleProp<ViewStyle>;
114
+ /** Hide "Your Result" label */
115
+ hideLabel?: boolean;
116
+ /** Show icon-only action buttons */
117
+ iconOnly?: boolean;
118
+ /** Show try again button */
119
+ showTryAgain?: boolean;
110
120
  }
111
121
 
112
122
  /**
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { useState, useCallback, useEffect } from "react";
7
- import { useIsFocused } from "@react-navigation/native";
7
+ import { useAppIsFocused } from "@umituz/react-native-design-system";
8
8
  import { MessageType, MessageTone } from "../../domain/types";
9
9
  import { generateLoveMessage } from "../../infrastructure/services/LoveMessageService";
10
10
  import { PartnerProfileRepository } from "../../infrastructure/persistence/PartnerProfileRepository";
@@ -20,7 +20,7 @@ export const useLoveMessageGenerator = (config: {
20
20
  onBack: () => void;
21
21
  initialType?: MessageType;
22
22
  }) => {
23
- const isFocused = useIsFocused();
23
+ const isFocused = useAppIsFocused();
24
24
 
25
25
  const [currentStep, setCurrentStep] = useState<GeneratorStep>(GeneratorStep.PARTNER);
26
26
  const [partnerName, setPartnerName] = useState("");
@@ -11,9 +11,9 @@ import {
11
11
  useAppDesignTokens,
12
12
  useSafeAreaInsets,
13
13
  AppNavigation,
14
+ useAppRoute,
14
15
  } from "@umituz/react-native-design-system";
15
16
  import { useLocalization } from "@umituz/react-native-localization";
16
- import { useRoute, RouteProp } from "@react-navigation/native";
17
17
  import { ProgressDots } from "../components/ProgressDots";
18
18
  import { MessageResult } from "../components/MessageResult";
19
19
  import { GeneratorHeader } from "../components/GeneratorHeader";
@@ -29,7 +29,7 @@ export const LoveMessageGeneratorScreen: FC = () => {
29
29
  const tokens = useAppDesignTokens();
30
30
  const { bottom } = useSafeAreaInsets();
31
31
  const { t } = useLocalization();
32
- const route = useRoute<RouteProp<{ params: RouteParams }, "params">>();
32
+ const route = useAppRoute<{ params: RouteParams }, "params">();
33
33
 
34
34
  const initialType = route.params?.initialType;
35
35
  const gen = useLoveMessageGenerator({ onBack: () => AppNavigation.goBack(), initialType });
@@ -10,9 +10,9 @@ import {
10
10
  useAppDesignTokens,
11
11
  useSafeAreaInsets,
12
12
  AppNavigation,
13
+ useAppRoute,
13
14
  } from "@umituz/react-native-design-system";
14
15
  import { useLocalization } from "@umituz/react-native-localization";
15
- import { useRoute, RouteProp } from "@react-navigation/native";
16
16
  import { CATEGORY_TEMPLATES, MESSAGE_TYPES } from "../../domain/constants";
17
17
  import { MessageListItem } from "../components/MessageListItem";
18
18
  import type { MessageType } from "../../domain/types";
@@ -23,7 +23,7 @@ export const MessageListScreen: FC = () => {
23
23
  const tokens = useAppDesignTokens();
24
24
  const { top, bottom } = useSafeAreaInsets();
25
25
  const { t } = useLocalization();
26
- const route = useRoute<RouteProp<{ params: RouteParams }, "params">>();
26
+ const route = useAppRoute<{ params: RouteParams }, "params">();
27
27
 
28
28
  const categoryId = route.params?.categoryId ?? "romantic";
29
29
  const messages = useMemo(() => CATEGORY_TEMPLATES[categoryId] || [], [categoryId]);