@umituz/react-native-ai-generation-content 1.12.31 → 1.12.33

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.12.31",
3
+ "version": "1.12.33",
4
4
  "description": "Provider-agnostic AI generation orchestration for React Native",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -12,6 +12,7 @@ export interface Creation {
12
12
  readonly originalUri?: string;
13
13
  readonly createdAt: Date;
14
14
  readonly isShared: boolean;
15
+ readonly isFavorite: boolean;
15
16
  }
16
17
 
17
18
  export interface CreationDocument {
@@ -26,6 +27,7 @@ export interface CreationDocument {
26
27
  readonly type?: string;
27
28
  readonly status?: string;
28
29
  readonly isShared: boolean;
30
+ readonly isFavorite?: boolean;
29
31
  readonly createdAt: FirebaseTimestamp | Date; // Allow Date for writing
30
32
  readonly completedAt?: FirebaseTimestamp | Date;
31
33
  }
@@ -56,5 +58,6 @@ export function mapDocumentToCreation(
56
58
  originalUri: data.originalImageUrl || data.originalImage,
57
59
  createdAt: creationDate,
58
60
  isShared: data.isShared ?? false,
61
+ isFavorite: data.isFavorite ?? false,
59
62
  };
60
63
  }
@@ -20,4 +20,9 @@ export interface ICreationsRepository {
20
20
  creationId: string,
21
21
  isShared: boolean,
22
22
  ): Promise<boolean>;
23
+ updateFavorite(
24
+ userId: string,
25
+ creationId: string,
26
+ isFavorite: boolean,
27
+ ): Promise<boolean>;
23
28
  }
@@ -238,4 +238,20 @@ export class CreationsRepository
238
238
  return false;
239
239
  }
240
240
  }
241
+
242
+ async updateFavorite(
243
+ userId: string,
244
+ creationId: string,
245
+ isFavorite: boolean,
246
+ ): Promise<boolean> {
247
+ const docRef = this.getDocRef(userId, creationId);
248
+ if (!docRef) return false;
249
+
250
+ try {
251
+ await updateDoc(docRef, { isFavorite });
252
+ return true;
253
+ } catch {
254
+ return false;
255
+ }
256
+ }
241
257
  }
@@ -19,6 +19,7 @@ interface CreationCardProps {
19
19
  readonly onView?: (creation: Creation) => void;
20
20
  readonly onShare: (creation: Creation) => void;
21
21
  readonly onDelete: (creation: Creation) => void;
22
+ readonly onFavorite?: (creation: Creation, isFavorite: boolean) => void;
22
23
  }
23
24
 
24
25
  export function CreationCard({
@@ -27,6 +28,7 @@ export function CreationCard({
27
28
  onView,
28
29
  onShare,
29
30
  onDelete,
31
+ onFavorite,
30
32
  }: CreationCardProps) {
31
33
  const tokens = useAppDesignTokens();
32
34
 
@@ -40,6 +42,10 @@ export function CreationCard({
40
42
  () => onDelete(creation),
41
43
  [creation, onDelete],
42
44
  );
45
+ const handleFavorite = useCallback(
46
+ () => onFavorite?.(creation, !creation.isFavorite),
47
+ [creation, onFavorite],
48
+ );
43
49
 
44
50
  const formattedDate = useMemo(() => {
45
51
  const date =
@@ -112,7 +118,7 @@ export function CreationCard({
112
118
  <View style={styles.content}>
113
119
  <View>
114
120
  <View style={styles.typeRow}>
115
- <AtomicText style={styles.icon}>{icon}</AtomicText>
121
+ <AtomicIcon name={icon} size="sm" color="primary" />
116
122
  <AtomicText style={styles.typeText}>{label}</AtomicText>
117
123
  </View>
118
124
  <AtomicText style={styles.dateText}>{formattedDate}</AtomicText>
@@ -123,6 +129,15 @@ export function CreationCard({
123
129
  <AtomicIcon name="eye" size="sm" color="primary" />
124
130
  </TouchableOpacity>
125
131
  )}
132
+ {onFavorite && (
133
+ <TouchableOpacity style={styles.actionBtn} onPress={handleFavorite}>
134
+ <AtomicIcon
135
+ name={creation.isFavorite ? "heart" : "heart-outline"}
136
+ size="sm"
137
+ color={creation.isFavorite ? "error" : "primary"}
138
+ />
139
+ </TouchableOpacity>
140
+ )}
126
141
  <TouchableOpacity style={styles.actionBtn} onPress={handleShare}>
127
142
  <AtomicIcon name="share-social" size="sm" color="primary" />
128
143
  </TouchableOpacity>
@@ -13,6 +13,7 @@ interface CreationsGridProps {
13
13
  readonly onView: (creation: Creation) => void;
14
14
  readonly onShare: (creation: Creation) => void;
15
15
  readonly onDelete: (creation: Creation) => void;
16
+ readonly onFavorite?: (creation: Creation, isFavorite: boolean) => void;
16
17
  readonly contentContainerStyle?: ViewStyle;
17
18
  readonly ListEmptyComponent?: React.ReactElement | null;
18
19
  readonly ListHeaderComponent?: React.ComponentType<unknown> | React.ReactElement | null;
@@ -26,6 +27,7 @@ export const CreationsGrid: React.FC<CreationsGridProps> = ({
26
27
  onView,
27
28
  onShare,
28
29
  onDelete,
30
+ onFavorite,
29
31
  contentContainerStyle,
30
32
  ListEmptyComponent,
31
33
  ListHeaderComponent,
@@ -40,6 +42,7 @@ export const CreationsGrid: React.FC<CreationsGridProps> = ({
40
42
  onView={() => onView(item)}
41
43
  onShare={() => onShare(item)}
42
44
  onDelete={() => onDelete(item)}
45
+ onFavorite={onFavorite ? (creation, isFavorite) => onFavorite(creation, isFavorite) : undefined}
43
46
  />
44
47
  );
45
48
 
@@ -95,6 +95,15 @@ export function CreationsGalleryScreen({
95
95
  setSelectedCreation(creation);
96
96
  }, []);
97
97
 
98
+ // Handle favorite toggle
99
+ const handleFavorite = useCallback(async (creation: Creation, isFavorite: boolean) => {
100
+ if (!userId) return;
101
+ const success = await repository.updateFavorite(userId, creation.id, isFavorite);
102
+ if (success) {
103
+ void refetch();
104
+ }
105
+ }, [userId, repository, refetch]);
106
+
98
107
  const styles = useStyles(tokens);
99
108
 
100
109
  const renderEmptyComponent = useMemo(() => (
@@ -152,6 +161,7 @@ export function CreationsGalleryScreen({
152
161
  onView={handleView}
153
162
  onShare={handleShare}
154
163
  onDelete={handleDelete}
164
+ onFavorite={handleFavorite}
155
165
  contentContainerStyle={{ paddingBottom: insets.bottom + tokens.spacing.xl }}
156
166
  ListEmptyComponent={renderEmptyComponent}
157
167
  />