@umituz/react-native-ai-creations 1.2.11 → 1.2.12
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 +5 -4
- package/src/presentation/components/CreationDetail/DetailActions.tsx +74 -0
- package/src/presentation/components/CreationDetail/DetailHeader.tsx +81 -0
- package/src/presentation/components/CreationDetail/DetailImage.tsx +46 -0
- package/src/presentation/components/CreationDetail/DetailStory.tsx +67 -0
- package/src/presentation/components/GalleryHeader.tsx +4 -2
- package/src/presentation/screens/CreationDetailScreen.tsx +71 -0
- package/src/presentation/screens/CreationsGalleryScreen.tsx +33 -13
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-ai-creations",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.12",
|
|
4
4
|
"description": "AI-generated creations gallery with filtering, sharing, and management for React Native apps",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -28,10 +28,11 @@
|
|
|
28
28
|
"url": "https://github.com/umituz/react-native-ai-creations"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
+
"@umituz/react-native-alert": "latest",
|
|
32
|
+
"@umituz/react-native-bottom-sheet": "latest",
|
|
31
33
|
"@umituz/react-native-filter": "latest",
|
|
32
34
|
"@umituz/react-native-image": "latest",
|
|
33
|
-
"
|
|
34
|
-
"@umituz/react-native-alert": "latest"
|
|
35
|
+
"expo-linear-gradient": "^15.0.8"
|
|
35
36
|
},
|
|
36
37
|
"peerDependencies": {
|
|
37
38
|
"@tanstack/react-query": ">=5.0.0",
|
|
@@ -47,8 +48,8 @@
|
|
|
47
48
|
"@tanstack/react-query": "^5.62.16",
|
|
48
49
|
"@types/react": "^19.0.0",
|
|
49
50
|
"@umituz/react-native-design-system": "latest",
|
|
50
|
-
"@umituz/react-native-sharing": "latest",
|
|
51
51
|
"@umituz/react-native-firestore": "latest",
|
|
52
|
+
"@umituz/react-native-sharing": "latest",
|
|
52
53
|
"firebase": "^11.0.0",
|
|
53
54
|
"react": "19.1.0",
|
|
54
55
|
"react-native": "0.81.5",
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { View, StyleSheet, TouchableOpacity } from 'react-native';
|
|
4
|
+
import { AtomicText, AtomicIcon, useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
5
|
+
|
|
6
|
+
interface DetailActionsProps {
|
|
7
|
+
readonly onShare: () => void;
|
|
8
|
+
readonly onDelete: () => void;
|
|
9
|
+
readonly shareLabel: string;
|
|
10
|
+
readonly deleteLabel: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const DetailActions: React.FC<DetailActionsProps> = ({
|
|
14
|
+
onShare,
|
|
15
|
+
onDelete,
|
|
16
|
+
shareLabel,
|
|
17
|
+
deleteLabel
|
|
18
|
+
}) => {
|
|
19
|
+
const tokens = useAppDesignTokens();
|
|
20
|
+
const styles = useStyles(tokens);
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<View style={styles.container}>
|
|
24
|
+
<TouchableOpacity
|
|
25
|
+
style={[styles.button, styles.shareButton]}
|
|
26
|
+
onPress={onShare}
|
|
27
|
+
>
|
|
28
|
+
<AtomicIcon name="share-social" size="sm" color="#fff" />
|
|
29
|
+
<AtomicText style={styles.buttonText}>{shareLabel}</AtomicText>
|
|
30
|
+
</TouchableOpacity>
|
|
31
|
+
|
|
32
|
+
<TouchableOpacity
|
|
33
|
+
style={[styles.button, styles.deleteButton]}
|
|
34
|
+
onPress={onDelete}
|
|
35
|
+
>
|
|
36
|
+
<AtomicIcon name="trash" size="sm" color={tokens.colors.error} />
|
|
37
|
+
<AtomicText style={[styles.buttonText, { color: tokens.colors.error }]}>
|
|
38
|
+
{deleteLabel}
|
|
39
|
+
</AtomicText>
|
|
40
|
+
</TouchableOpacity>
|
|
41
|
+
</View>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const useStyles = (tokens: any) => StyleSheet.create({
|
|
46
|
+
container: {
|
|
47
|
+
flexDirection: 'row',
|
|
48
|
+
justifyContent: 'center',
|
|
49
|
+
gap: tokens.spacing.md,
|
|
50
|
+
paddingHorizontal: tokens.spacing.lg,
|
|
51
|
+
marginBottom: tokens.spacing.xxl,
|
|
52
|
+
},
|
|
53
|
+
button: {
|
|
54
|
+
flexDirection: 'row',
|
|
55
|
+
alignItems: 'center',
|
|
56
|
+
justifyContent: 'center',
|
|
57
|
+
paddingVertical: 12,
|
|
58
|
+
paddingHorizontal: 24,
|
|
59
|
+
borderRadius: 16,
|
|
60
|
+
gap: 8,
|
|
61
|
+
minWidth: 120,
|
|
62
|
+
},
|
|
63
|
+
shareButton: {
|
|
64
|
+
backgroundColor: tokens.colors.primary,
|
|
65
|
+
},
|
|
66
|
+
deleteButton: {
|
|
67
|
+
backgroundColor: tokens.colors.error + '10',
|
|
68
|
+
},
|
|
69
|
+
buttonText: {
|
|
70
|
+
fontWeight: '700',
|
|
71
|
+
color: '#fff',
|
|
72
|
+
fontSize: 15,
|
|
73
|
+
},
|
|
74
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { View, StyleSheet, TouchableOpacity } from 'react-native';
|
|
4
|
+
import { AtomicText, AtomicIcon, useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
5
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
6
|
+
|
|
7
|
+
interface DetailHeaderProps {
|
|
8
|
+
readonly title: string;
|
|
9
|
+
readonly date: string;
|
|
10
|
+
readonly onClose: () => void;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const DetailHeader: React.FC<DetailHeaderProps> = ({ title, date, onClose }) => {
|
|
14
|
+
const tokens = useAppDesignTokens();
|
|
15
|
+
const insets = useSafeAreaInsets();
|
|
16
|
+
const styles = useStyles(tokens, insets);
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<View style={styles.headerContainer}>
|
|
20
|
+
<TouchableOpacity style={styles.closeButton} onPress={onClose}>
|
|
21
|
+
<AtomicIcon name="arrow-back" size={24} customColor={tokens.colors.textPrimary} />
|
|
22
|
+
</TouchableOpacity>
|
|
23
|
+
|
|
24
|
+
<View style={styles.titleContainer}>
|
|
25
|
+
<AtomicText style={styles.title} numberOfLines={1}>{title}</AtomicText>
|
|
26
|
+
<View style={styles.dateBadge}>
|
|
27
|
+
<AtomicIcon name="calendar-outline" size={12} customColor={tokens.colors.primary} />
|
|
28
|
+
<AtomicText style={styles.dateText}>{date}</AtomicText>
|
|
29
|
+
</View>
|
|
30
|
+
</View>
|
|
31
|
+
|
|
32
|
+
<View style={styles.placeholder} />
|
|
33
|
+
</View>
|
|
34
|
+
);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const useStyles = (tokens: any, insets: any) => StyleSheet.create({
|
|
38
|
+
headerContainer: {
|
|
39
|
+
flexDirection: 'row',
|
|
40
|
+
alignItems: 'center',
|
|
41
|
+
paddingTop: insets.top + tokens.spacing.sm,
|
|
42
|
+
paddingBottom: tokens.spacing.md,
|
|
43
|
+
paddingHorizontal: tokens.spacing.md,
|
|
44
|
+
backgroundColor: tokens.colors.backgroundPrimary,
|
|
45
|
+
borderBottomWidth: 1,
|
|
46
|
+
borderBottomColor: tokens.colors.border,
|
|
47
|
+
zIndex: 10,
|
|
48
|
+
},
|
|
49
|
+
closeButton: {
|
|
50
|
+
padding: tokens.spacing.xs,
|
|
51
|
+
marginRight: tokens.spacing.sm,
|
|
52
|
+
},
|
|
53
|
+
titleContainer: {
|
|
54
|
+
flex: 1,
|
|
55
|
+
alignItems: 'center',
|
|
56
|
+
},
|
|
57
|
+
title: {
|
|
58
|
+
fontSize: 18,
|
|
59
|
+
fontWeight: '700',
|
|
60
|
+
color: tokens.colors.textPrimary,
|
|
61
|
+
marginBottom: 4,
|
|
62
|
+
textAlign: 'center',
|
|
63
|
+
},
|
|
64
|
+
dateBadge: {
|
|
65
|
+
flexDirection: 'row',
|
|
66
|
+
alignItems: 'center',
|
|
67
|
+
gap: 4,
|
|
68
|
+
paddingHorizontal: 10,
|
|
69
|
+
paddingVertical: 4,
|
|
70
|
+
borderRadius: 12,
|
|
71
|
+
backgroundColor: tokens.colors.primary + '15',
|
|
72
|
+
},
|
|
73
|
+
dateText: {
|
|
74
|
+
fontSize: 12,
|
|
75
|
+
fontWeight: '600',
|
|
76
|
+
color: tokens.colors.primary,
|
|
77
|
+
},
|
|
78
|
+
placeholder: {
|
|
79
|
+
width: 40,
|
|
80
|
+
},
|
|
81
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { View, StyleSheet, Image, Dimensions } from 'react-native';
|
|
4
|
+
import { useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
5
|
+
|
|
6
|
+
interface DetailImageProps {
|
|
7
|
+
readonly uri: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const { width } = Dimensions.get('window');
|
|
11
|
+
|
|
12
|
+
export const DetailImage: React.FC<DetailImageProps> = ({ uri }) => {
|
|
13
|
+
const tokens = useAppDesignTokens();
|
|
14
|
+
const styles = useStyles(tokens);
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<View style={styles.container}>
|
|
18
|
+
<View style={styles.frame}>
|
|
19
|
+
<Image source={{ uri }} style={styles.image} resizeMode="cover" />
|
|
20
|
+
</View>
|
|
21
|
+
</View>
|
|
22
|
+
);
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const useStyles = (tokens: any) => StyleSheet.create({
|
|
26
|
+
container: {
|
|
27
|
+
paddingHorizontal: tokens.spacing.lg,
|
|
28
|
+
marginVertical: tokens.spacing.lg,
|
|
29
|
+
},
|
|
30
|
+
frame: {
|
|
31
|
+
width: width - (tokens.spacing.lg * 2),
|
|
32
|
+
height: width - (tokens.spacing.lg * 2),
|
|
33
|
+
borderRadius: 24,
|
|
34
|
+
overflow: 'hidden',
|
|
35
|
+
backgroundColor: tokens.colors.surface,
|
|
36
|
+
shadowColor: "#000",
|
|
37
|
+
shadowOffset: { width: 0, height: 8 },
|
|
38
|
+
shadowOpacity: 0.2,
|
|
39
|
+
shadowRadius: 16,
|
|
40
|
+
elevation: 8,
|
|
41
|
+
},
|
|
42
|
+
image: {
|
|
43
|
+
width: '100%',
|
|
44
|
+
height: '100%',
|
|
45
|
+
},
|
|
46
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { View, StyleSheet } from 'react-native';
|
|
4
|
+
import { AtomicText, useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
5
|
+
import { LinearGradient } from 'expo-linear-gradient';
|
|
6
|
+
|
|
7
|
+
interface DetailStoryProps {
|
|
8
|
+
readonly story: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const DetailStory: React.FC<DetailStoryProps> = ({ story }) => {
|
|
12
|
+
const tokens = useAppDesignTokens();
|
|
13
|
+
const styles = useStyles(tokens);
|
|
14
|
+
|
|
15
|
+
if (!story) return null;
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<View style={styles.container}>
|
|
19
|
+
<LinearGradient
|
|
20
|
+
colors={[tokens.colors.primary + '15', tokens.colors.primary + '05']}
|
|
21
|
+
style={styles.gradient}
|
|
22
|
+
>
|
|
23
|
+
<AtomicText style={styles.quoteMark}>"</AtomicText>
|
|
24
|
+
<AtomicText style={styles.text}>{story}</AtomicText>
|
|
25
|
+
<View style={styles.quoteEndRow}>
|
|
26
|
+
<AtomicText style={[styles.quoteMark, styles.quoteEnd]}>"</AtomicText>
|
|
27
|
+
</View>
|
|
28
|
+
</LinearGradient>
|
|
29
|
+
</View>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const useStyles = (tokens: any) => StyleSheet.create({
|
|
34
|
+
container: {
|
|
35
|
+
paddingHorizontal: tokens.spacing.lg,
|
|
36
|
+
marginBottom: tokens.spacing.lg,
|
|
37
|
+
},
|
|
38
|
+
gradient: {
|
|
39
|
+
padding: tokens.spacing.lg,
|
|
40
|
+
borderRadius: 20,
|
|
41
|
+
borderWidth: 1,
|
|
42
|
+
borderColor: tokens.colors.primary + '20',
|
|
43
|
+
},
|
|
44
|
+
quoteMark: {
|
|
45
|
+
fontSize: 48,
|
|
46
|
+
lineHeight: 48,
|
|
47
|
+
color: tokens.colors.primary,
|
|
48
|
+
opacity: 0.4,
|
|
49
|
+
marginBottom: -16,
|
|
50
|
+
},
|
|
51
|
+
quoteEndRow: {
|
|
52
|
+
alignItems: 'flex-end',
|
|
53
|
+
marginTop: -16,
|
|
54
|
+
},
|
|
55
|
+
quoteEnd: {
|
|
56
|
+
marginBottom: 0,
|
|
57
|
+
},
|
|
58
|
+
text: {
|
|
59
|
+
fontSize: 16,
|
|
60
|
+
lineHeight: 26,
|
|
61
|
+
textAlign: 'center',
|
|
62
|
+
fontStyle: 'italic',
|
|
63
|
+
fontWeight: '500',
|
|
64
|
+
color: tokens.colors.textPrimary,
|
|
65
|
+
paddingBottom: 4,
|
|
66
|
+
},
|
|
67
|
+
});
|
|
@@ -8,6 +8,7 @@ interface GalleryHeaderProps {
|
|
|
8
8
|
readonly countLabel: string;
|
|
9
9
|
readonly isFiltered: boolean;
|
|
10
10
|
readonly onFilterPress: () => void;
|
|
11
|
+
readonly style?: any;
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
export const GalleryHeader: React.FC<GalleryHeaderProps> = ({
|
|
@@ -15,13 +16,14 @@ export const GalleryHeader: React.FC<GalleryHeaderProps> = ({
|
|
|
15
16
|
count,
|
|
16
17
|
countLabel,
|
|
17
18
|
isFiltered,
|
|
18
|
-
onFilterPress
|
|
19
|
+
onFilterPress,
|
|
20
|
+
style,
|
|
19
21
|
}) => {
|
|
20
22
|
const tokens = useAppDesignTokens();
|
|
21
23
|
const styles = useStyles(tokens);
|
|
22
24
|
|
|
23
25
|
return (
|
|
24
|
-
<View style={styles.headerArea}>
|
|
26
|
+
<View style={[styles.headerArea, style]}>
|
|
25
27
|
<View>
|
|
26
28
|
<AtomicText style={styles.title}>{title}</AtomicText>
|
|
27
29
|
<AtomicText style={styles.subtitle}>
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { View, StyleSheet, ScrollView } from 'react-native';
|
|
4
|
+
import { useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
5
|
+
import type { Creation } from '../../domain/entities/Creation';
|
|
6
|
+
import { DetailHeader } from '../components/CreationDetail/DetailHeader';
|
|
7
|
+
import { DetailImage } from '../components/CreationDetail/DetailImage';
|
|
8
|
+
import { DetailStory } from '../components/CreationDetail/DetailStory';
|
|
9
|
+
import { DetailActions } from '../components/CreationDetail/DetailActions';
|
|
10
|
+
|
|
11
|
+
interface CreationDetailScreenProps {
|
|
12
|
+
readonly creation: Creation;
|
|
13
|
+
readonly onClose: () => void;
|
|
14
|
+
readonly onShare: (creation: Creation) => void;
|
|
15
|
+
readonly onDelete: (creation: Creation) => void;
|
|
16
|
+
readonly t: (key: string) => string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const CreationDetailScreen: React.FC<CreationDetailScreenProps> = ({
|
|
20
|
+
creation,
|
|
21
|
+
onClose,
|
|
22
|
+
onShare,
|
|
23
|
+
onDelete,
|
|
24
|
+
t
|
|
25
|
+
}) => {
|
|
26
|
+
const tokens = useAppDesignTokens();
|
|
27
|
+
|
|
28
|
+
// Extract data
|
|
29
|
+
const metadata = (creation as any).metadata || {};
|
|
30
|
+
const title = metadata.names || creation.type;
|
|
31
|
+
const story = metadata.story || metadata.description || "";
|
|
32
|
+
const date = metadata.date || new Date(creation.createdAt).toLocaleDateString();
|
|
33
|
+
|
|
34
|
+
const styles = useStyles(tokens);
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<View style={styles.container}>
|
|
38
|
+
<DetailHeader
|
|
39
|
+
title={title}
|
|
40
|
+
date={date}
|
|
41
|
+
onClose={onClose}
|
|
42
|
+
/>
|
|
43
|
+
|
|
44
|
+
<ScrollView
|
|
45
|
+
contentContainerStyle={styles.scrollContent}
|
|
46
|
+
showsVerticalScrollIndicator={false}
|
|
47
|
+
>
|
|
48
|
+
<DetailImage uri={creation.uri} />
|
|
49
|
+
|
|
50
|
+
<DetailStory story={story} />
|
|
51
|
+
|
|
52
|
+
<DetailActions
|
|
53
|
+
onShare={() => onShare(creation)}
|
|
54
|
+
onDelete={() => onDelete(creation)}
|
|
55
|
+
shareLabel={t("result.shareButton") || "Share"}
|
|
56
|
+
deleteLabel={t("common.delete") || "Delete"}
|
|
57
|
+
/>
|
|
58
|
+
</ScrollView>
|
|
59
|
+
</View>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const useStyles = (tokens: any) => StyleSheet.create({
|
|
64
|
+
container: {
|
|
65
|
+
flex: 1,
|
|
66
|
+
backgroundColor: tokens.colors.backgroundPrimary,
|
|
67
|
+
},
|
|
68
|
+
scrollContent: {
|
|
69
|
+
paddingBottom: tokens.spacing.xxl,
|
|
70
|
+
},
|
|
71
|
+
});
|
|
@@ -23,6 +23,7 @@ import { AtomicIcon, AtomicText } from "@umituz/react-native-design-system";
|
|
|
23
23
|
import { GalleryHeader } from "../components/GalleryHeader";
|
|
24
24
|
|
|
25
25
|
import { useAlert } from "@umituz/react-native-alert";
|
|
26
|
+
import { CreationDetailScreen } from "./CreationDetailScreen";
|
|
26
27
|
|
|
27
28
|
interface CreationsGalleryScreenProps {
|
|
28
29
|
readonly userId: string | null;
|
|
@@ -49,8 +50,12 @@ export function CreationsGalleryScreen({
|
|
|
49
50
|
const insets = useSafeAreaInsets();
|
|
50
51
|
const { share } = useSharing();
|
|
51
52
|
const alert = useAlert();
|
|
53
|
+
|
|
54
|
+
// State
|
|
52
55
|
const [viewerVisible, setViewerVisible] = useState(false);
|
|
53
56
|
const [viewerIndex, setViewerIndex] = useState(0);
|
|
57
|
+
const [selectedCreation, setSelectedCreation] = useState<Creation | null>(null);
|
|
58
|
+
|
|
54
59
|
const filterSheetRef = React.useRef<BottomSheetModalRef>(null);
|
|
55
60
|
|
|
56
61
|
const { data: creations, isLoading, refetch } = useCreations({
|
|
@@ -65,7 +70,6 @@ export function CreationsGalleryScreen({
|
|
|
65
70
|
const allCategories = useMemo(() => {
|
|
66
71
|
const categories: FilterCategory[] = [];
|
|
67
72
|
|
|
68
|
-
// Add dynamic types category if types exist
|
|
69
73
|
if (config.types.length > 0) {
|
|
70
74
|
categories.push({
|
|
71
75
|
id: 'type',
|
|
@@ -86,16 +90,13 @@ export function CreationsGalleryScreen({
|
|
|
86
90
|
return categories;
|
|
87
91
|
}, [config.types, config.filterCategories, t]);
|
|
88
92
|
|
|
89
|
-
const handleView = useCallback(
|
|
90
|
-
(creation
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
},
|
|
97
|
-
[filtered],
|
|
98
|
-
);
|
|
93
|
+
const handleView = useCallback((creation: Creation) => {
|
|
94
|
+
setSelectedCreation(creation);
|
|
95
|
+
}, []);
|
|
96
|
+
|
|
97
|
+
const handleCloseDetail = useCallback(() => {
|
|
98
|
+
setSelectedCreation(null);
|
|
99
|
+
}, []);
|
|
99
100
|
|
|
100
101
|
const handleShare = useCallback(
|
|
101
102
|
async (creation: Creation) => {
|
|
@@ -129,7 +130,10 @@ export function CreationsGalleryScreen({
|
|
|
129
130
|
label: t("common.delete"),
|
|
130
131
|
style: 'destructive',
|
|
131
132
|
variant: 'danger',
|
|
132
|
-
onPress: () =>
|
|
133
|
+
onPress: () => {
|
|
134
|
+
deleteMutation.mutate(creation.id);
|
|
135
|
+
setSelectedCreation(null);
|
|
136
|
+
},
|
|
133
137
|
},
|
|
134
138
|
]
|
|
135
139
|
});
|
|
@@ -173,7 +177,7 @@ export function CreationsGalleryScreen({
|
|
|
173
177
|
<CreationCard
|
|
174
178
|
creation={item}
|
|
175
179
|
types={config.types}
|
|
176
|
-
onView={handleView}
|
|
180
|
+
onView={() => handleView(item)}
|
|
177
181
|
onShare={handleShare}
|
|
178
182
|
onDelete={handleDelete}
|
|
179
183
|
/>
|
|
@@ -181,6 +185,19 @@ export function CreationsGalleryScreen({
|
|
|
181
185
|
[config.types, handleView, handleShare, handleDelete],
|
|
182
186
|
);
|
|
183
187
|
|
|
188
|
+
// If a creation is selected, show detail screen (simulating a stack push)
|
|
189
|
+
if (selectedCreation) {
|
|
190
|
+
return (
|
|
191
|
+
<CreationDetailScreen
|
|
192
|
+
creation={selectedCreation}
|
|
193
|
+
onClose={handleCloseDetail}
|
|
194
|
+
onShare={handleShare}
|
|
195
|
+
onDelete={handleDelete}
|
|
196
|
+
t={t}
|
|
197
|
+
/>
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
184
201
|
if (!isLoading && (!creations || creations.length === 0)) {
|
|
185
202
|
return (
|
|
186
203
|
<View style={styles.container}>
|
|
@@ -202,6 +219,7 @@ export function CreationsGalleryScreen({
|
|
|
202
219
|
countLabel={t(config.translations.photoCount) || 'photos'}
|
|
203
220
|
isFiltered={isFiltered}
|
|
204
221
|
onFilterPress={() => filterSheetRef.current?.present()}
|
|
222
|
+
style={{ paddingTop: insets.top }}
|
|
205
223
|
/>
|
|
206
224
|
|
|
207
225
|
<FlatList
|
|
@@ -217,6 +235,8 @@ export function CreationsGalleryScreen({
|
|
|
217
235
|
/>
|
|
218
236
|
}
|
|
219
237
|
/>
|
|
238
|
+
|
|
239
|
+
{/* Optional: Keep ImageGallery for quick preview if needed, or rely on Detail Screen */}
|
|
220
240
|
<ImageGallery
|
|
221
241
|
images={viewerImages}
|
|
222
242
|
visible={viewerVisible}
|