@umituz/react-native-ai-generation-content 1.17.117 → 1.17.119

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.117",
3
+ "version": "1.17.119",
4
4
  "description": "Provider-agnostic AI generation orchestration for React Native",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -1,26 +1,37 @@
1
1
  import React from 'react';
2
- import { View, StyleSheet, useWindowDimensions } from 'react-native';
2
+ import { View, StyleSheet, useWindowDimensions, TouchableOpacity } from 'react-native';
3
3
  import { useAppDesignTokens } from "@umituz/react-native-design-system";
4
4
  import { Image } from 'expo-image';
5
5
 
6
6
  interface DetailImageProps {
7
7
  readonly uri: string;
8
+ readonly onPress?: () => void;
8
9
  }
9
10
 
10
11
  const HORIZONTAL_PADDING = 16;
11
12
  const ASPECT_RATIO = 16 / 9;
12
13
 
13
- export const DetailImage: React.FC<DetailImageProps> = ({ uri }) => {
14
+ export const DetailImage: React.FC<DetailImageProps> = ({ uri, onPress }) => {
14
15
  const tokens = useAppDesignTokens();
15
16
  const { width } = useWindowDimensions();
16
17
  const imageWidth = width - (HORIZONTAL_PADDING * 2);
17
18
  const imageHeight = imageWidth / ASPECT_RATIO;
18
19
 
20
+ const content = (
21
+ <View style={[styles.frame, { width: imageWidth, height: imageHeight, backgroundColor: tokens.colors.surface }]}>
22
+ <Image source={{ uri }} style={styles.image} contentFit="cover" />
23
+ </View>
24
+ );
25
+
19
26
  return (
20
27
  <View style={styles.container}>
21
- <View style={[styles.frame, { width: imageWidth, height: imageHeight, backgroundColor: tokens.colors.surface }]}>
22
- <Image source={{ uri }} style={styles.image} contentFit="cover" />
23
- </View>
28
+ {onPress ? (
29
+ <TouchableOpacity activeOpacity={0.9} onPress={onPress}>
30
+ {content}
31
+ </TouchableOpacity>
32
+ ) : (
33
+ content
34
+ )}
24
35
  </View>
25
36
  );
26
37
  };
@@ -1,7 +1,8 @@
1
- import React, { useMemo } from 'react';
1
+ import React, { useMemo, useState, useCallback } from 'react';
2
2
  import { View, ScrollView, StyleSheet } from 'react-native';
3
3
  import { useSafeAreaInsets } from 'react-native-safe-area-context';
4
4
  import { useAppDesignTokens } from "@umituz/react-native-design-system";
5
+ import { ImageGallery } from "@umituz/react-native-image";
5
6
  import type { Creation } from '../../domain/entities/Creation';
6
7
  import type { CreationsConfig } from '../../domain/value-objects/CreationsConfig';
7
8
  import { hasVideoContent, getPreviewUrl } from '../../domain/utils';
@@ -41,6 +42,15 @@ export const CreationDetailScreen: React.FC<CreationDetailScreenProps> = ({
41
42
  }) => {
42
43
  const tokens = useAppDesignTokens();
43
44
  const insets = useSafeAreaInsets();
45
+ const [showFullScreen, setShowFullScreen] = useState(false);
46
+
47
+ const handleImagePress = useCallback(() => {
48
+ setShowFullScreen(true);
49
+ }, []);
50
+
51
+ const handleDismissFullScreen = useCallback(() => {
52
+ setShowFullScreen(false);
53
+ }, []);
44
54
 
45
55
  // Extract data safely
46
56
  const metadata = (creation.metadata || {}) as CreationMetadata;
@@ -81,7 +91,7 @@ export const CreationDetailScreen: React.FC<CreationDetailScreenProps> = ({
81
91
  {isVideo ? (
82
92
  <DetailVideo videoUrl={videoUrl} thumbnailUrl={thumbnailUrl} />
83
93
  ) : (
84
- <DetailImage uri={creation.uri} />
94
+ <DetailImage uri={creation.uri} onPress={handleImagePress} />
85
95
  )}
86
96
 
87
97
  {story ? (
@@ -95,6 +105,15 @@ export const CreationDetailScreen: React.FC<CreationDetailScreenProps> = ({
95
105
  deleteLabel={t("common.delete")}
96
106
  />
97
107
  </ScrollView>
108
+
109
+ {!isVideo && (
110
+ <ImageGallery
111
+ images={[{ uri: creation.uri }]}
112
+ visible={showFullScreen}
113
+ onDismiss={handleDismissFullScreen}
114
+ index={0}
115
+ />
116
+ )}
98
117
  </View>
99
118
  );
100
119
  };
@@ -1,74 +0,0 @@
1
-
2
- import { generateUUID } from "@umituz/react-native-uuid";
3
- import type { ICreationsRepository } from "../../domain/repositories/ICreationsRepository";
4
- import type { ICreationsStorageService } from "../../domain/services/ICreationsStorageService";
5
- import type { CreationType } from "../../domain/value-objects";
6
- import { BaseRepository } from "@umituz/react-native-firebase";
7
- import type { Creation } from "../../domain/entities/Creation";
8
-
9
- export interface CreateCreationDTO {
10
- userId: string;
11
- type: CreationType;
12
- prompt: string;
13
- metadata?: Record<string, unknown>;
14
- imageUri: string; // can be local file uri or base64
15
- aspectRatio?: number;
16
- }
17
-
18
- export class CreationsService extends BaseRepository {
19
- constructor(
20
- private readonly repository: ICreationsRepository,
21
- private readonly storageService: ICreationsStorageService,
22
- private readonly _collectionName: string = "creations" // Default to generic name, app can override via repo
23
- ) {
24
- super();
25
- }
26
-
27
- async saveCreation(dto: CreateCreationDTO): Promise<string> {
28
- const db = this.getDb();
29
- if (!db) throw new Error("Firestore not initialized");
30
-
31
- try {
32
- const creationId = generateUUID();
33
-
34
- const imageUrl = await this.storageService.uploadCreationImage(
35
- dto.userId,
36
- creationId,
37
- dto.imageUri
38
- );
39
-
40
- await this.repository.create(dto.userId, {
41
- id: creationId,
42
- uri: imageUrl,
43
- type: dto.type.id,
44
- prompt: dto.prompt,
45
- metadata: dto.metadata || {},
46
- createdAt: new Date(),
47
- isShared: false,
48
- isFavorite: false,
49
- });
50
-
51
- return creationId;
52
- } catch (error) {
53
- // eslint-disable-next-line no-console
54
- console.error(error);
55
- throw error;
56
- }
57
- }
58
-
59
- async getCreation(userId: string, id: string): Promise<Creation | null> {
60
- return this.repository.getById(userId, id);
61
- }
62
-
63
- async updateCreation(
64
- userId: string,
65
- id: string,
66
- updates: { metadata?: Record<string, unknown> },
67
- ): Promise<boolean> {
68
- return this.repository.update(userId, id, updates);
69
- }
70
-
71
- async deleteCreation(userId: string, id: string): Promise<boolean> {
72
- return this.repository.delete(userId, id);
73
- }
74
- }
@@ -1,13 +0,0 @@
1
- export interface ICreationsStorageService {
2
- uploadCreationImage(
3
- userId: string,
4
- creationId: string,
5
- imageUri: string,
6
- mimeType?: string
7
- ): Promise<string>;
8
-
9
- deleteCreationImage(
10
- userId: string,
11
- creationId: string
12
- ): Promise<boolean>;
13
- }
@@ -1,49 +0,0 @@
1
- import {
2
- uploadFile,
3
- uploadBase64Image,
4
- } from "@umituz/react-native-firebase";
5
- import type { ICreationsStorageService } from "../../domain/services/ICreationsStorageService";
6
-
7
- declare const __DEV__: boolean;
8
-
9
- export class CreationsStorageService implements ICreationsStorageService {
10
- constructor(private readonly storagePathPrefix: string = "creations") { }
11
-
12
- private getPath(userId: string, creationId: string): string {
13
- return `${this.storagePathPrefix}/${userId}/${creationId}.jpg`;
14
- }
15
-
16
- async uploadCreationImage(
17
- userId: string,
18
- creationId: string,
19
- imageUri: string,
20
- mimeType = "image/jpeg"
21
- ): Promise<string> {
22
- const path = this.getPath(userId, creationId);
23
-
24
- try {
25
- if (imageUri.startsWith("data:")) {
26
- const result = await uploadBase64Image(imageUri, path, { mimeType });
27
- return result.downloadUrl;
28
- }
29
- const result = await uploadFile(imageUri, path, { mimeType });
30
- return result.downloadUrl;
31
- } catch (error) {
32
- if (__DEV__) {
33
- // eslint-disable-next-line no-console
34
- console.error("[CreationsStorageService] upload failed", error);
35
- }
36
- throw error;
37
- }
38
- }
39
-
40
- async deleteCreationImage(
41
- _userId: string,
42
- _creationId: string
43
- ): Promise<boolean> {
44
- // Delete logic not strictly required for saving loop, but good to have
45
- // Needs storage reference delete implementation in rn-firebase first
46
- // For now we skip implementing delete in this iteration as priority is saving
47
- return Promise.resolve(true);
48
- }
49
- }