@umituz/react-native-ai-generation-content 1.16.0 → 1.17.1
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 +13 -14
- package/src/domains/creations/domain/entities/Creation.ts +33 -2
- package/src/domains/creations/domain/entities/index.ts +1 -1
- package/src/domains/creations/domain/types/creation-categories.ts +133 -0
- package/src/domains/creations/domain/types/creation-filter.ts +131 -0
- package/src/domains/creations/domain/types/creation-types.ts +63 -0
- package/src/domains/creations/domain/types/index.ts +44 -0
- package/src/domains/creations/domain/utils/creation-helpers.ts +134 -0
- package/src/domains/creations/domain/utils/index.ts +8 -0
- package/src/domains/creations/domain/utils/preview-helpers.ts +84 -0
- package/src/domains/creations/domain/utils/status-helpers.ts +90 -0
- package/src/domains/creations/index.ts +95 -21
- package/src/domains/creations/infrastructure/repositories/CreationsRepository.ts +14 -1
- package/src/domains/creations/presentation/components/CreationActions.tsx +120 -0
- package/src/domains/creations/presentation/components/CreationBadges.tsx +111 -0
- package/src/domains/creations/presentation/components/CreationCard.tsx +201 -102
- package/src/domains/creations/presentation/components/CreationPreview.tsx +117 -0
- package/src/domains/creations/presentation/components/CreationsFilterBar.tsx +254 -0
- package/src/domains/creations/presentation/components/CreationsGrid.tsx +121 -68
- package/src/domains/creations/presentation/components/index.ts +23 -3
- package/src/domains/creations/presentation/hooks/index.ts +1 -0
- package/src/domains/creations/presentation/hooks/useAdvancedFilter.ts +262 -0
- package/src/domains/creations/presentation/screens/CreationsGalleryScreen.tsx +5 -6
- package/src/features/ai-hug/domain/index.ts +5 -0
- package/src/features/ai-hug/domain/types/ai-hug.types.ts +72 -0
- package/src/features/ai-hug/domain/types/index.ts +14 -0
- package/src/features/ai-hug/index.ts +27 -0
- package/src/features/ai-hug/infrastructure/index.ts +5 -0
- package/src/features/ai-hug/infrastructure/services/ai-hug-executor.ts +96 -0
- package/src/features/ai-hug/infrastructure/services/index.ts +6 -0
- package/src/features/ai-hug/presentation/hooks/index.ts +9 -0
- package/src/features/ai-hug/presentation/hooks/useAIHugFeature.ts +157 -0
- package/src/features/ai-hug/presentation/index.ts +5 -0
- package/src/features/ai-kiss/domain/index.ts +5 -0
- package/src/features/ai-kiss/domain/types/ai-kiss.types.ts +72 -0
- package/src/features/ai-kiss/domain/types/index.ts +14 -0
- package/src/features/ai-kiss/index.ts +27 -0
- package/src/features/ai-kiss/infrastructure/index.ts +5 -0
- package/src/features/ai-kiss/infrastructure/services/ai-kiss-executor.ts +96 -0
- package/src/features/ai-kiss/infrastructure/services/index.ts +6 -0
- package/src/features/ai-kiss/presentation/hooks/index.ts +9 -0
- package/src/features/ai-kiss/presentation/hooks/useAIKissFeature.ts +157 -0
- package/src/features/ai-kiss/presentation/index.ts +5 -0
- package/src/features/anime-selfie/domain/index.ts +5 -0
- package/src/features/anime-selfie/domain/types/anime-selfie.types.ts +72 -0
- package/src/features/anime-selfie/domain/types/index.ts +15 -0
- package/src/features/anime-selfie/index.ts +28 -0
- package/src/features/anime-selfie/infrastructure/index.ts +5 -0
- package/src/features/anime-selfie/infrastructure/services/anime-selfie-executor.ts +95 -0
- package/src/features/anime-selfie/infrastructure/services/index.ts +6 -0
- package/src/features/anime-selfie/presentation/hooks/index.ts +9 -0
- package/src/features/anime-selfie/presentation/hooks/useAnimeSelfieFeature.ts +138 -0
- package/src/features/anime-selfie/presentation/index.ts +5 -0
- package/src/features/background/domain/types/index.ts +15 -0
- package/src/features/background/domain/types/replace-background.types.ts +82 -0
- package/src/features/background/index.ts +31 -3
- package/src/features/background/infrastructure/index.ts +5 -0
- package/src/features/background/infrastructure/services/index.ts +6 -0
- package/src/features/background/infrastructure/services/replace-background-executor.ts +95 -0
- package/src/features/background/presentation/hooks/index.ts +6 -1
- package/src/features/background/presentation/hooks/useReplaceBackgroundFeature.ts +160 -0
- package/src/features/face-swap/domain/index.ts +5 -0
- package/src/features/face-swap/domain/types/face-swap.types.ts +72 -0
- package/src/features/face-swap/domain/types/index.ts +14 -0
- package/src/features/face-swap/index.ts +27 -1
- package/src/features/face-swap/infrastructure/index.ts +5 -0
- package/src/features/face-swap/infrastructure/services/face-swap-executor.ts +96 -0
- package/src/features/face-swap/infrastructure/services/index.ts +6 -0
- package/src/features/face-swap/presentation/hooks/index.ts +9 -0
- package/src/features/face-swap/presentation/hooks/useFaceSwapFeature.ts +157 -0
- package/src/features/face-swap/presentation/index.ts +5 -0
- package/src/features/photo-restoration/domain/index.ts +1 -0
- package/src/features/photo-restoration/domain/types/index.ts +10 -0
- package/src/features/photo-restoration/domain/types/photo-restore.types.ts +71 -0
- package/src/features/photo-restoration/index.ts +34 -1
- package/src/features/photo-restoration/infrastructure/index.ts +1 -0
- package/src/features/photo-restoration/infrastructure/services/index.ts +2 -0
- package/src/features/photo-restoration/infrastructure/services/photo-restore-executor.ts +98 -0
- package/src/features/photo-restoration/presentation/components/PhotoRestoreFeature.tsx +175 -0
- package/src/features/photo-restoration/presentation/components/PhotoRestoreResultView.tsx +98 -0
- package/src/features/photo-restoration/presentation/components/index.ts +4 -0
- package/src/features/photo-restoration/presentation/hooks/index.ts +5 -0
- package/src/features/photo-restoration/presentation/hooks/usePhotoRestoreFeature.ts +137 -0
- package/src/features/photo-restoration/presentation/index.ts +2 -0
- package/src/features/remove-background/domain/index.ts +5 -0
- package/src/features/remove-background/domain/types/index.ts +14 -0
- package/src/features/remove-background/domain/types/remove-background.types.ts +69 -0
- package/src/features/remove-background/index.ts +27 -0
- package/src/features/remove-background/infrastructure/index.ts +5 -0
- package/src/features/remove-background/infrastructure/services/index.ts +6 -0
- package/src/features/remove-background/infrastructure/services/remove-background-executor.ts +95 -0
- package/src/features/remove-background/presentation/hooks/index.ts +9 -0
- package/src/features/remove-background/presentation/hooks/useRemoveBackgroundFeature.ts +137 -0
- package/src/features/remove-background/presentation/index.ts +5 -0
- package/src/features/remove-object/domain/index.ts +5 -0
- package/src/features/remove-object/domain/types/index.ts +14 -0
- package/src/features/remove-object/domain/types/remove-object.types.ts +77 -0
- package/src/features/remove-object/index.ts +27 -0
- package/src/features/remove-object/infrastructure/index.ts +5 -0
- package/src/features/remove-object/infrastructure/services/index.ts +6 -0
- package/src/features/remove-object/infrastructure/services/remove-object-executor.ts +99 -0
- package/src/features/remove-object/presentation/hooks/index.ts +9 -0
- package/src/features/remove-object/presentation/hooks/useRemoveObjectFeature.ts +168 -0
- package/src/features/remove-object/presentation/index.ts +5 -0
- package/src/features/upscaling/domain/types/index.ts +0 -1
- package/src/features/upscaling/domain/types/upscale.types.ts +14 -0
- package/src/features/upscaling/index.ts +3 -11
- package/src/features/upscaling/infrastructure/services/index.ts +1 -6
- package/src/features/upscaling/infrastructure/services/upscale-executor.ts +64 -30
- package/src/features/upscaling/presentation/hooks/useUpscaleFeature.ts +12 -7
- package/src/index.ts +45 -0
- package/src/types/jsx.d.ts +19 -0
- package/src/features/face-swap/domain/entities.ts +0 -48
- package/src/features/photo-restoration/domain/entities.ts +0 -48
- package/src/features/upscaling/domain/types/provider.types.ts +0 -23
- package/src/features/upscaling/infrastructure/services/upscale-provider-registry.ts +0 -77
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-ai-generation-content",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.17.1",
|
|
4
4
|
"description": "Provider-agnostic AI generation orchestration for React Native",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -59,24 +59,23 @@
|
|
|
59
59
|
"@react-native-async-storage/async-storage": "^2.2.0",
|
|
60
60
|
"@react-native-community/datetimepicker": "^8.5.1",
|
|
61
61
|
"@react-navigation/bottom-tabs": "^7.9.0",
|
|
62
|
-
"@react-navigation/native": "^
|
|
62
|
+
"@react-navigation/native": "^7.1.26",
|
|
63
63
|
"@react-navigation/stack": "^7.6.13",
|
|
64
64
|
"@tanstack/react-query": "^5.0.0",
|
|
65
65
|
"@types/react": "~19.1.10",
|
|
66
|
-
"@
|
|
67
|
-
"@typescript-eslint/
|
|
68
|
-
"@typescript-eslint/parser": "^7.0.0",
|
|
66
|
+
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
67
|
+
"@typescript-eslint/parser": "^8.0.0",
|
|
69
68
|
"@umituz/react-native-animation": "*",
|
|
70
|
-
"@umituz/react-native-design-system": "
|
|
71
|
-
"@umituz/react-native-firebase": "
|
|
72
|
-
"@umituz/react-native-haptics": "
|
|
69
|
+
"@umituz/react-native-design-system": "latest",
|
|
70
|
+
"@umituz/react-native-firebase": "latest",
|
|
71
|
+
"@umituz/react-native-haptics": "latest",
|
|
73
72
|
"@umituz/react-native-image": "*",
|
|
74
|
-
"@umituz/react-native-localization": "
|
|
73
|
+
"@umituz/react-native-localization": "latest",
|
|
75
74
|
"@umituz/react-native-offline": "*",
|
|
76
|
-
"@umituz/react-native-storage": "
|
|
77
|
-
"@umituz/react-native-timezone": "
|
|
75
|
+
"@umituz/react-native-storage": "latest",
|
|
76
|
+
"@umituz/react-native-timezone": "latest",
|
|
78
77
|
"@umituz/react-native-uuid": "*",
|
|
79
|
-
"eslint": "^
|
|
78
|
+
"eslint": "^9.0.0",
|
|
80
79
|
"expo-application": "^7.0.8",
|
|
81
80
|
"expo-clipboard": "^8.0.8",
|
|
82
81
|
"expo-crypto": "^15.0.8",
|
|
@@ -87,7 +86,7 @@
|
|
|
87
86
|
"expo-linear-gradient": "~15.0.7",
|
|
88
87
|
"expo-localization": "^17.0.8",
|
|
89
88
|
"expo-sharing": "^14.0.8",
|
|
90
|
-
"firebase": "^
|
|
89
|
+
"firebase": "^12.6.0",
|
|
91
90
|
"i18next": "^25.7.3",
|
|
92
91
|
"react": "19.1.0",
|
|
93
92
|
"react-i18next": "^16.5.0",
|
|
@@ -96,7 +95,7 @@
|
|
|
96
95
|
"react-native-reanimated": "^4.2.1",
|
|
97
96
|
"react-native-safe-area-context": "^5.6.2",
|
|
98
97
|
"rn-emoji-keyboard": "^1.7.0",
|
|
99
|
-
"typescript": "^5.
|
|
98
|
+
"typescript": "^5.9.0",
|
|
100
99
|
"zustand": "^5.0.2"
|
|
101
100
|
},
|
|
102
101
|
"publishConfig": {
|
|
@@ -3,6 +3,23 @@
|
|
|
3
3
|
* Represents an AI-generated creation
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import type { CreationStatus } from "../types/creation-types";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Creation output containing media URLs
|
|
10
|
+
*/
|
|
11
|
+
export interface CreationOutput {
|
|
12
|
+
readonly imageUrl?: string;
|
|
13
|
+
readonly imageUrls?: string[];
|
|
14
|
+
readonly videoUrl?: string;
|
|
15
|
+
readonly audioUrl?: string;
|
|
16
|
+
readonly thumbnailUrl?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Main Creation entity
|
|
21
|
+
* Supports both simple (uri-based) and complex (output-based) creations
|
|
22
|
+
*/
|
|
6
23
|
export interface Creation {
|
|
7
24
|
readonly id: string;
|
|
8
25
|
readonly uri: string;
|
|
@@ -13,6 +30,9 @@ export interface Creation {
|
|
|
13
30
|
readonly createdAt: Date;
|
|
14
31
|
readonly isShared: boolean;
|
|
15
32
|
readonly isFavorite: boolean;
|
|
33
|
+
// Extended fields for job-based creations
|
|
34
|
+
readonly status?: CreationStatus;
|
|
35
|
+
readonly output?: CreationOutput;
|
|
16
36
|
}
|
|
17
37
|
|
|
18
38
|
export interface CreationDocument {
|
|
@@ -26,9 +46,10 @@ export interface CreationDocument {
|
|
|
26
46
|
readonly transformationType?: string;
|
|
27
47
|
readonly type?: string;
|
|
28
48
|
readonly status?: string;
|
|
49
|
+
readonly output?: CreationOutput;
|
|
29
50
|
readonly isShared: boolean;
|
|
30
51
|
readonly isFavorite?: boolean;
|
|
31
|
-
readonly createdAt: FirebaseTimestamp | Date;
|
|
52
|
+
readonly createdAt: FirebaseTimestamp | Date;
|
|
32
53
|
readonly completedAt?: FirebaseTimestamp | Date;
|
|
33
54
|
}
|
|
34
55
|
|
|
@@ -49,9 +70,17 @@ export function mapDocumentToCreation(
|
|
|
49
70
|
creationDate = new Date();
|
|
50
71
|
}
|
|
51
72
|
|
|
73
|
+
// Get URI from output or direct fields
|
|
74
|
+
const uri = data.output?.imageUrl ||
|
|
75
|
+
data.output?.videoUrl ||
|
|
76
|
+
data.transformedImageUrl ||
|
|
77
|
+
data.transformedImage ||
|
|
78
|
+
data.uri ||
|
|
79
|
+
"";
|
|
80
|
+
|
|
52
81
|
return {
|
|
53
82
|
id,
|
|
54
|
-
uri
|
|
83
|
+
uri,
|
|
55
84
|
type: data.transformationType || data.type || "unknown",
|
|
56
85
|
prompt: data.prompt,
|
|
57
86
|
metadata: data.metadata,
|
|
@@ -59,5 +88,7 @@ export function mapDocumentToCreation(
|
|
|
59
88
|
createdAt: creationDate,
|
|
60
89
|
isShared: data.isShared ?? false,
|
|
61
90
|
isFavorite: data.isFavorite ?? false,
|
|
91
|
+
status: data.status as CreationStatus | undefined,
|
|
92
|
+
output: data.output,
|
|
62
93
|
};
|
|
63
94
|
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creation Categories
|
|
3
|
+
* Maps creation types to categories for filtering and organization
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { CreationTypeId, CreationCategory } from "./creation-types";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Image-related creation types
|
|
10
|
+
*/
|
|
11
|
+
export const IMAGE_CREATION_TYPES: CreationTypeId[] = [
|
|
12
|
+
"text-to-image",
|
|
13
|
+
"upscale",
|
|
14
|
+
"remove-background",
|
|
15
|
+
"photo-restore",
|
|
16
|
+
"inpainting",
|
|
17
|
+
"style-transfer",
|
|
18
|
+
"colorization",
|
|
19
|
+
"face-swap",
|
|
20
|
+
"object-removal",
|
|
21
|
+
"background-replacement",
|
|
22
|
+
"ai-brush",
|
|
23
|
+
"hd-touch-up",
|
|
24
|
+
"ai-hug",
|
|
25
|
+
"ai-kiss",
|
|
26
|
+
"anime-selfie",
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Video-related creation types
|
|
31
|
+
*/
|
|
32
|
+
export const VIDEO_CREATION_TYPES: CreationTypeId[] = [
|
|
33
|
+
"text-to-video",
|
|
34
|
+
"image-to-video",
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Voice-related creation types
|
|
39
|
+
*/
|
|
40
|
+
export const VOICE_CREATION_TYPES: CreationTypeId[] = ["text-to-voice"];
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* All creation types
|
|
44
|
+
*/
|
|
45
|
+
export const ALL_CREATION_TYPES: CreationTypeId[] = [
|
|
46
|
+
...IMAGE_CREATION_TYPES,
|
|
47
|
+
...VIDEO_CREATION_TYPES,
|
|
48
|
+
...VOICE_CREATION_TYPES,
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Get creation types for a category
|
|
53
|
+
*/
|
|
54
|
+
export function getTypesForCategory(
|
|
55
|
+
category: CreationCategory
|
|
56
|
+
): CreationTypeId[] {
|
|
57
|
+
switch (category) {
|
|
58
|
+
case "image":
|
|
59
|
+
return IMAGE_CREATION_TYPES;
|
|
60
|
+
case "video":
|
|
61
|
+
return VIDEO_CREATION_TYPES;
|
|
62
|
+
case "voice":
|
|
63
|
+
return VOICE_CREATION_TYPES;
|
|
64
|
+
case "all":
|
|
65
|
+
return ALL_CREATION_TYPES;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Get category for a creation type
|
|
71
|
+
*/
|
|
72
|
+
export function getCategoryForType(type: CreationTypeId): CreationCategory {
|
|
73
|
+
if (IMAGE_CREATION_TYPES.includes(type)) {
|
|
74
|
+
return "image";
|
|
75
|
+
}
|
|
76
|
+
if (VIDEO_CREATION_TYPES.includes(type)) {
|
|
77
|
+
return "video";
|
|
78
|
+
}
|
|
79
|
+
if (VOICE_CREATION_TYPES.includes(type)) {
|
|
80
|
+
return "voice";
|
|
81
|
+
}
|
|
82
|
+
return "image"; // Default fallback
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Check if a type belongs to a category
|
|
87
|
+
*/
|
|
88
|
+
export function isTypeInCategory(
|
|
89
|
+
type: CreationTypeId,
|
|
90
|
+
category: CreationCategory
|
|
91
|
+
): boolean {
|
|
92
|
+
if (category === "all") {
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
return getTypesForCategory(category).includes(type);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Check if creation type is video
|
|
100
|
+
*/
|
|
101
|
+
export function isVideoCreationType(type?: string): boolean {
|
|
102
|
+
if (!type) return false;
|
|
103
|
+
return VIDEO_CREATION_TYPES.includes(type as CreationTypeId);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Check if creation type is image
|
|
108
|
+
*/
|
|
109
|
+
export function isImageCreationType(type?: string): boolean {
|
|
110
|
+
if (!type) return false;
|
|
111
|
+
return IMAGE_CREATION_TYPES.includes(type as CreationTypeId);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Check if creation type is voice
|
|
116
|
+
*/
|
|
117
|
+
export function isVoiceCreationType(type?: string): boolean {
|
|
118
|
+
if (!type) return false;
|
|
119
|
+
return VOICE_CREATION_TYPES.includes(type as CreationTypeId);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Get media type (image/video/audio) for a creation type
|
|
124
|
+
*/
|
|
125
|
+
export function getMediaTypeForCreation(
|
|
126
|
+
type?: string
|
|
127
|
+
): "image" | "video" | "audio" | "unknown" {
|
|
128
|
+
if (!type) return "unknown";
|
|
129
|
+
if (isVideoCreationType(type)) return "video";
|
|
130
|
+
if (isVoiceCreationType(type)) return "audio";
|
|
131
|
+
if (isImageCreationType(type)) return "image";
|
|
132
|
+
return "unknown";
|
|
133
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creation Filter Types
|
|
3
|
+
* Advanced filtering options for creations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { CreationTypeId, CreationStatus, CreationCategory } from "./creation-types";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Filter options for querying creations
|
|
10
|
+
*/
|
|
11
|
+
export interface CreationFilter {
|
|
12
|
+
/** Filter by specific type, category, or all */
|
|
13
|
+
type?: CreationTypeId | CreationCategory;
|
|
14
|
+
/** Filter by status */
|
|
15
|
+
status?: CreationStatus | "all";
|
|
16
|
+
/** Filter by date range start (timestamp in ms) */
|
|
17
|
+
startDate?: number;
|
|
18
|
+
/** Filter by date range end (timestamp in ms) */
|
|
19
|
+
endDate?: number;
|
|
20
|
+
/** Search query for prompt or metadata */
|
|
21
|
+
searchQuery?: string;
|
|
22
|
+
/** Sort field */
|
|
23
|
+
sortField?: "createdAt" | "updatedAt" | "type" | "status";
|
|
24
|
+
/** Sort order */
|
|
25
|
+
sortOrder?: "asc" | "desc";
|
|
26
|
+
/** Limit number of results */
|
|
27
|
+
limit?: number;
|
|
28
|
+
/** Cursor for pagination (timestamp in ms) */
|
|
29
|
+
cursor?: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Default filter configuration
|
|
34
|
+
*/
|
|
35
|
+
export const DEFAULT_CREATION_FILTER: CreationFilter = {
|
|
36
|
+
type: "all",
|
|
37
|
+
status: "all",
|
|
38
|
+
sortField: "createdAt",
|
|
39
|
+
sortOrder: "desc",
|
|
40
|
+
limit: 50,
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Filter option for UI display
|
|
45
|
+
*/
|
|
46
|
+
export interface FilterOption {
|
|
47
|
+
id: string;
|
|
48
|
+
/** Display label (use labelKey for i18n) */
|
|
49
|
+
label?: string;
|
|
50
|
+
/** i18n key for label */
|
|
51
|
+
labelKey?: string;
|
|
52
|
+
icon?: string;
|
|
53
|
+
count?: number;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Media filter options
|
|
58
|
+
*/
|
|
59
|
+
export const MEDIA_FILTER_OPTIONS: FilterOption[] = [
|
|
60
|
+
{ id: "all", labelKey: "creations.filter.all", icon: "Grid" },
|
|
61
|
+
{ id: "image", labelKey: "creations.filter.images", icon: "Image" },
|
|
62
|
+
{ id: "video", labelKey: "creations.filter.videos", icon: "Video" },
|
|
63
|
+
{ id: "voice", labelKey: "creations.filter.voice", icon: "Mic" },
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Status filter options
|
|
68
|
+
*/
|
|
69
|
+
export const STATUS_FILTER_OPTIONS: FilterOption[] = [
|
|
70
|
+
{ id: "all", labelKey: "creations.filter.allStatus", icon: "List" },
|
|
71
|
+
{ id: "completed", labelKey: "creations.filter.completed", icon: "CheckCircle" },
|
|
72
|
+
{ id: "processing", labelKey: "creations.filter.processing", icon: "Loader" },
|
|
73
|
+
{ id: "failed", labelKey: "creations.filter.failed", icon: "XCircle" },
|
|
74
|
+
{ id: "pending", labelKey: "creations.filter.pending", icon: "Clock" },
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Creation statistics
|
|
79
|
+
*/
|
|
80
|
+
export interface CreationStats {
|
|
81
|
+
total: number;
|
|
82
|
+
byCategory: Record<CreationCategory, number>;
|
|
83
|
+
byStatus: Record<CreationStatus, number>;
|
|
84
|
+
byType: Partial<Record<CreationTypeId, number>>;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Calculate stats from creations array
|
|
89
|
+
*/
|
|
90
|
+
export function calculateCreationStats(
|
|
91
|
+
creations: Array<{ type?: string; status?: string }>
|
|
92
|
+
): CreationStats {
|
|
93
|
+
const stats: CreationStats = {
|
|
94
|
+
total: creations.length,
|
|
95
|
+
byCategory: { all: creations.length, image: 0, video: 0, voice: 0 },
|
|
96
|
+
byStatus: { pending: 0, queued: 0, processing: 0, completed: 0, failed: 0 },
|
|
97
|
+
byType: {},
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
for (const creation of creations) {
|
|
101
|
+
// Count by type
|
|
102
|
+
if (creation.type) {
|
|
103
|
+
const typeId = creation.type as CreationTypeId;
|
|
104
|
+
stats.byType[typeId] = (stats.byType[typeId] || 0) + 1;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Count by status
|
|
108
|
+
if (creation.status) {
|
|
109
|
+
const status = creation.status as CreationStatus;
|
|
110
|
+
if (status in stats.byStatus) {
|
|
111
|
+
stats.byStatus[status]++;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Calculate category counts from type counts
|
|
117
|
+
const { IMAGE_CREATION_TYPES, VIDEO_CREATION_TYPES, VOICE_CREATION_TYPES } =
|
|
118
|
+
require("./creation-categories");
|
|
119
|
+
|
|
120
|
+
for (const [typeId, count] of Object.entries(stats.byType)) {
|
|
121
|
+
if (IMAGE_CREATION_TYPES.includes(typeId)) {
|
|
122
|
+
stats.byCategory.image += count as number;
|
|
123
|
+
} else if (VIDEO_CREATION_TYPES.includes(typeId)) {
|
|
124
|
+
stats.byCategory.video += count as number;
|
|
125
|
+
} else if (VOICE_CREATION_TYPES.includes(typeId)) {
|
|
126
|
+
stats.byCategory.voice += count as number;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return stats;
|
|
131
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creation Types
|
|
3
|
+
* Core type definitions for AI-generated creations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* All supported creation types
|
|
8
|
+
*/
|
|
9
|
+
export type CreationTypeId =
|
|
10
|
+
| "text-to-image"
|
|
11
|
+
| "text-to-video"
|
|
12
|
+
| "image-to-video"
|
|
13
|
+
| "text-to-voice"
|
|
14
|
+
| "upscale"
|
|
15
|
+
| "remove-background"
|
|
16
|
+
| "photo-restore"
|
|
17
|
+
| "inpainting"
|
|
18
|
+
| "style-transfer"
|
|
19
|
+
| "colorization"
|
|
20
|
+
| "face-swap"
|
|
21
|
+
| "object-removal"
|
|
22
|
+
| "background-replacement"
|
|
23
|
+
| "ai-brush"
|
|
24
|
+
| "hd-touch-up"
|
|
25
|
+
| "ai-hug"
|
|
26
|
+
| "ai-kiss"
|
|
27
|
+
| "anime-selfie";
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Creation status values
|
|
31
|
+
*/
|
|
32
|
+
export type CreationStatus =
|
|
33
|
+
| "pending"
|
|
34
|
+
| "queued"
|
|
35
|
+
| "processing"
|
|
36
|
+
| "completed"
|
|
37
|
+
| "failed";
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Creation category for grouping types
|
|
41
|
+
*/
|
|
42
|
+
export type CreationCategory = "image" | "video" | "voice" | "all";
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* All status values as array for iteration
|
|
46
|
+
*/
|
|
47
|
+
export const ALL_CREATION_STATUSES: CreationStatus[] = [
|
|
48
|
+
"pending",
|
|
49
|
+
"queued",
|
|
50
|
+
"processing",
|
|
51
|
+
"completed",
|
|
52
|
+
"failed",
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* All categories as array for iteration
|
|
57
|
+
*/
|
|
58
|
+
export const ALL_CREATION_CATEGORIES: CreationCategory[] = [
|
|
59
|
+
"all",
|
|
60
|
+
"image",
|
|
61
|
+
"video",
|
|
62
|
+
"voice",
|
|
63
|
+
];
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creation Domain Types
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
// Core types
|
|
6
|
+
export type {
|
|
7
|
+
CreationTypeId,
|
|
8
|
+
CreationStatus,
|
|
9
|
+
CreationCategory,
|
|
10
|
+
} from "./creation-types";
|
|
11
|
+
|
|
12
|
+
export {
|
|
13
|
+
ALL_CREATION_STATUSES,
|
|
14
|
+
ALL_CREATION_CATEGORIES,
|
|
15
|
+
} from "./creation-types";
|
|
16
|
+
|
|
17
|
+
// Category system
|
|
18
|
+
export {
|
|
19
|
+
IMAGE_CREATION_TYPES,
|
|
20
|
+
VIDEO_CREATION_TYPES,
|
|
21
|
+
VOICE_CREATION_TYPES,
|
|
22
|
+
ALL_CREATION_TYPES,
|
|
23
|
+
getTypesForCategory,
|
|
24
|
+
getCategoryForType,
|
|
25
|
+
isTypeInCategory,
|
|
26
|
+
isVideoCreationType,
|
|
27
|
+
isImageCreationType,
|
|
28
|
+
isVoiceCreationType,
|
|
29
|
+
getMediaTypeForCreation,
|
|
30
|
+
} from "./creation-categories";
|
|
31
|
+
|
|
32
|
+
// Filter types
|
|
33
|
+
export type {
|
|
34
|
+
CreationFilter,
|
|
35
|
+
FilterOption,
|
|
36
|
+
CreationStats,
|
|
37
|
+
} from "./creation-filter";
|
|
38
|
+
|
|
39
|
+
export {
|
|
40
|
+
DEFAULT_CREATION_FILTER,
|
|
41
|
+
MEDIA_FILTER_OPTIONS,
|
|
42
|
+
STATUS_FILTER_OPTIONS,
|
|
43
|
+
calculateCreationStats,
|
|
44
|
+
} from "./creation-filter";
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creation Helpers
|
|
3
|
+
* Utility functions for creation data manipulation
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { CreationTypeId } from "../types";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Icon name type for design system
|
|
10
|
+
*/
|
|
11
|
+
export type IconName = "image" | "film" | "mic" | "sparkles" | "color-palette" | "brush";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Get icon name for creation type
|
|
15
|
+
*/
|
|
16
|
+
export function getTypeIcon(type: CreationTypeId): IconName {
|
|
17
|
+
switch (type) {
|
|
18
|
+
case "text-to-video":
|
|
19
|
+
case "image-to-video":
|
|
20
|
+
return "film";
|
|
21
|
+
case "text-to-voice":
|
|
22
|
+
return "mic";
|
|
23
|
+
case "style-transfer":
|
|
24
|
+
case "colorization":
|
|
25
|
+
return "color-palette";
|
|
26
|
+
case "ai-brush":
|
|
27
|
+
case "inpainting":
|
|
28
|
+
return "brush";
|
|
29
|
+
default:
|
|
30
|
+
return "image";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Get i18n key for creation type
|
|
36
|
+
*/
|
|
37
|
+
export function getTypeTextKey(type: CreationTypeId): string {
|
|
38
|
+
return `creations.types.${type}`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Get formatted type text (fallback)
|
|
43
|
+
*/
|
|
44
|
+
export function getTypeText(type: CreationTypeId): string {
|
|
45
|
+
return type.split("-").map(word =>
|
|
46
|
+
word.charAt(0).toUpperCase() + word.slice(1)
|
|
47
|
+
).join(" ");
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Get creation title from prompt or type
|
|
52
|
+
*/
|
|
53
|
+
export function getCreationTitle(
|
|
54
|
+
prompt?: string,
|
|
55
|
+
type?: CreationTypeId,
|
|
56
|
+
maxLength: number = 50
|
|
57
|
+
): string {
|
|
58
|
+
if (prompt && prompt.length > 0) {
|
|
59
|
+
return prompt.length > maxLength
|
|
60
|
+
? prompt.substring(0, maxLength) + "..."
|
|
61
|
+
: prompt;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (type) {
|
|
65
|
+
return getTypeText(type);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return "Untitled Creation";
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Filter creations by search query (client-side)
|
|
73
|
+
*/
|
|
74
|
+
export function filterBySearch<T extends { prompt?: string; type?: string; provider?: string }>(
|
|
75
|
+
items: T[],
|
|
76
|
+
searchQuery?: string,
|
|
77
|
+
): T[] {
|
|
78
|
+
if (!searchQuery || searchQuery.trim().length === 0) {
|
|
79
|
+
return items;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const query = searchQuery.toLowerCase().trim();
|
|
83
|
+
|
|
84
|
+
return items.filter((item) =>
|
|
85
|
+
item.prompt?.toLowerCase().includes(query) ||
|
|
86
|
+
item.type?.toLowerCase().includes(query) ||
|
|
87
|
+
item.provider?.toLowerCase().includes(query)
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Sort creations by field
|
|
93
|
+
*/
|
|
94
|
+
export function sortCreations<T extends Record<string, unknown>>(
|
|
95
|
+
items: T[],
|
|
96
|
+
field: keyof T,
|
|
97
|
+
order: "asc" | "desc" = "desc"
|
|
98
|
+
): T[] {
|
|
99
|
+
return [...items].sort((a, b) => {
|
|
100
|
+
const aVal = a[field] as unknown;
|
|
101
|
+
const bVal = b[field] as unknown;
|
|
102
|
+
|
|
103
|
+
if (aVal === undefined && bVal === undefined) return 0;
|
|
104
|
+
if (aVal === undefined) return 1;
|
|
105
|
+
if (bVal === undefined) return -1;
|
|
106
|
+
|
|
107
|
+
if (typeof aVal === "string" && typeof bVal === "string") {
|
|
108
|
+
return order === "desc"
|
|
109
|
+
? bVal.localeCompare(aVal)
|
|
110
|
+
: aVal.localeCompare(bVal);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (typeof aVal === "number" && typeof bVal === "number") {
|
|
114
|
+
return order === "desc" ? bVal - aVal : aVal - bVal;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Handle Date objects
|
|
118
|
+
if (aVal instanceof Date && bVal instanceof Date) {
|
|
119
|
+
return order === "desc"
|
|
120
|
+
? bVal.getTime() - aVal.getTime()
|
|
121
|
+
: aVal.getTime() - bVal.getTime();
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return 0;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Truncate text with ellipsis
|
|
130
|
+
*/
|
|
131
|
+
export function truncateText(text: string, maxLength: number): string {
|
|
132
|
+
if (text.length <= maxLength) return text;
|
|
133
|
+
return text.substring(0, maxLength - 3) + "...";
|
|
134
|
+
}
|