@umituz/react-native-design-system 4.23.97 → 4.23.100

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.
Files changed (35) hide show
  1. package/package.json +1 -1
  2. package/src/atoms/button/AtomicButton.tsx +7 -0
  3. package/src/atoms/button/types/index.ts +4 -0
  4. package/src/atoms/input/hooks/useInputState.ts +3 -7
  5. package/src/haptics/infrastructure/services/HapticService.ts +1 -1
  6. package/src/media/infrastructure/hooks/useGenericMediaGeneration.ts +170 -0
  7. package/src/media/presentation/hooks/useCardMediaGeneration.ts +9 -113
  8. package/src/media/presentation/hooks/useCardMediaUpload.ts +5 -5
  9. package/src/media/presentation/hooks/useCardMediaValidation.ts +4 -1
  10. package/src/media/presentation/hooks/useMediaGeneration.ts +4 -87
  11. package/src/molecules/navigation/components/NavigationHeader.tsx +3 -3
  12. package/src/offline/index.ts +1 -0
  13. package/src/offline/infrastructure/storage/OfflineConfigStore.ts +34 -0
  14. package/src/offline/presentation/hooks/useOffline.ts +8 -4
  15. package/src/storage/domain/utils/devUtils.ts +0 -24
  16. package/src/storage/index.ts +1 -1
  17. package/src/storage/infrastructure/adapters/StorageService.ts +2 -7
  18. package/src/storage/infrastructure/repositories/BaseStorageOperations.ts +0 -3
  19. package/src/storage/presentation/hooks/CacheStorageOperations.ts +2 -8
  20. package/src/storage/presentation/hooks/useStore.ts +14 -5
  21. package/src/utilities/sharing/presentation/hooks/useSharing.ts +3 -3
  22. package/src/layouts/ScreenLayout/ScreenLayout.example.tsx +0 -92
  23. package/src/media/domain/entities/CardMultimedia.types.ts +0 -120
  24. package/src/media/infrastructure/services/CardMediaGenerationService.README.md +0 -99
  25. package/src/media/infrastructure/services/CardMediaGenerationService.ts +0 -101
  26. package/src/media/infrastructure/services/CardMediaOptimizerService.README.md +0 -167
  27. package/src/media/infrastructure/services/CardMediaOptimizerService.ts +0 -36
  28. package/src/media/infrastructure/services/CardMediaUploadService.README.md +0 -123
  29. package/src/media/infrastructure/services/CardMediaUploadService.ts +0 -62
  30. package/src/media/infrastructure/services/CardMediaValidationService.README.md +0 -134
  31. package/src/media/infrastructure/services/CardMediaValidationService.ts +0 -81
  32. package/src/media/presentation/hooks/useCardMediaGeneration.README.md +0 -164
  33. package/src/media/presentation/hooks/useCardMediaUpload.README.md +0 -153
  34. package/src/media/presentation/hooks/useCardMediaValidation.README.md +0 -176
  35. package/src/storage/domain/utils/__tests__/devUtils.test.ts +0 -97
@@ -6,7 +6,6 @@
6
6
  */
7
7
 
8
8
  import AsyncStorage from '@react-native-async-storage/async-storage';
9
- import { devWarn } from '../../domain/utils/devUtils';
10
9
  import type { StateStorage } from '../../domain/types/Store';
11
10
 
12
11
  /**
@@ -18,8 +17,6 @@ export const storageService: StateStorage = {
18
17
  try {
19
18
  return await AsyncStorage.getItem(name);
20
19
  } catch (error) {
21
- const errorMessage = `StorageService: Failed to get item "${name}"`;
22
- devWarn(errorMessage, error);
23
20
  return null;
24
21
  }
25
22
  },
@@ -28,8 +25,7 @@ export const storageService: StateStorage = {
28
25
  try {
29
26
  await AsyncStorage.setItem(name, value);
30
27
  } catch (error) {
31
- const errorMessage = `StorageService: Failed to set item "${name}"`;
32
- devWarn(errorMessage, error);
28
+ // Silent failure
33
29
  }
34
30
  },
35
31
 
@@ -37,8 +33,7 @@ export const storageService: StateStorage = {
37
33
  try {
38
34
  await AsyncStorage.removeItem(name);
39
35
  } catch (error) {
40
- const errorMessage = `StorageService: Failed to remove item "${name}"`;
41
- devWarn(errorMessage, error);
36
+ // Silent failure
42
37
  }
43
38
  },
44
39
  };
@@ -14,7 +14,6 @@ import {
14
14
  StorageSerializationError,
15
15
  StorageDeserializationError,
16
16
  } from '../../domain/errors/StorageError';
17
- import { devWarn } from '../../domain/utils/devUtils';
18
17
 
19
18
  /**
20
19
  * Base storage operations implementation
@@ -81,8 +80,6 @@ export class BaseStorageOperations {
81
80
  const value = await AsyncStorage.getItem(key);
82
81
  return value !== null;
83
82
  } catch (error) {
84
- const errorMessage = `BaseStorageOperations: Failed to check if key "${key}" exists`;
85
- devWarn(errorMessage, error);
86
83
  return false;
87
84
  }
88
85
  }
@@ -7,7 +7,6 @@
7
7
  import { storageRepository } from '../../infrastructure/repositories/AsyncStorageRepository';
8
8
  import type { CachedValue } from '../../domain/entities/CachedValue';
9
9
  import { createCachedValue } from '../../domain/entities/CachedValue';
10
- import { devWarn } from '../../domain/utils/devUtils';
11
10
  import { isValidCachedValue } from '../../domain/utils/ValidationUtils';
12
11
 
13
12
  export interface CacheStorageOptions {
@@ -56,16 +55,11 @@ export class CacheStorageOperations {
56
55
  return parsed as CachedValue<T>;
57
56
  }
58
57
 
59
- if (__DEV__) {
60
- devWarn(`CacheStorageOperations: Invalid cached data structure for key "${key}"`);
61
- }
62
-
63
58
  return null;
64
59
  }
65
60
 
66
61
  return null;
67
62
  } catch (error) {
68
- devWarn(`CacheStorageOperations: Failed to load cache for key "${key}"`, error);
69
63
  return null;
70
64
  }
71
65
  }
@@ -86,7 +80,7 @@ export class CacheStorageOperations {
86
80
  const cached = createCachedValue(value, ttl || 0, version);
87
81
  await storageRepository.setString(key, JSON.stringify(cached));
88
82
  } catch (error) {
89
- devWarn(`CacheStorageOperations: Failed to save cache for key "${key}"`, error);
83
+ // Silent failure
90
84
  }
91
85
  }
92
86
 
@@ -99,7 +93,7 @@ export class CacheStorageOperations {
99
93
  try {
100
94
  await storageRepository.removeItem(key);
101
95
  } catch (error) {
102
- devWarn(`CacheStorageOperations: Failed to clear cache for key "${key}"`, error);
96
+ // Silent failure
103
97
  }
104
98
  }
105
99
  }
@@ -3,14 +3,23 @@
3
3
  * Helper for creating stores in components
4
4
  */
5
5
 
6
- import { useMemo, useRef } from 'react';
6
+ import { useMemo } from 'react';
7
7
  import { createStore } from '../../domain/factories/StoreFactory';
8
8
  import type { StoreConfig } from '../../domain/types/Store';
9
9
 
10
10
  export function useStore<T extends object>(config: StoreConfig<T>) {
11
- // Config objesini stabilize et - sadece name değiştiğinde yeni store oluştur
12
- const configRef = useRef(config);
13
- configRef.current = config;
14
- const store = useMemo(() => createStore(configRef.current), [config.name]);
11
+ // Stabilize entire config to track all property changes
12
+ const stableConfig = useMemo(
13
+ () => config,
14
+ [
15
+ config.name,
16
+ config.version,
17
+ config.persist,
18
+ config.storage,
19
+ config.ttl,
20
+ ]
21
+ );
22
+
23
+ const store = useMemo(() => createStore(stableConfig), [stableConfig]);
15
24
  return store;
16
25
  }
@@ -8,7 +8,7 @@
8
8
  * @layer presentation/hooks
9
9
  */
10
10
 
11
- import { useState, useCallback, useEffect } from 'react';
11
+ import { useState, useCallback, useEffect, useMemo } from 'react';
12
12
  import { SharingService } from '../../infrastructure/services/SharingService';
13
13
  import type { ShareOptions } from '../../domain/entities/Share';
14
14
 
@@ -140,7 +140,7 @@ export const useSharing = () => {
140
140
  []
141
141
  );
142
142
 
143
- return {
143
+ return useMemo(() => ({
144
144
  // Functions
145
145
  share,
146
146
  shareWithAutoType,
@@ -150,5 +150,5 @@ export const useSharing = () => {
150
150
  isAvailable,
151
151
  isSharing,
152
152
  error,
153
- };
153
+ }), [share, shareWithAutoType, shareMultiple, isAvailable, isSharing, error]);
154
154
  };
@@ -1,92 +0,0 @@
1
- /**
2
- * Enhanced ScreenLayout Example
3
- *
4
- * This demonstrates the recommended usage of ScreenLayout with SafeAreaProvider
5
- */
6
-
7
- import React from 'react';
8
- import { View, Text } from 'react-native';
9
- import {
10
- SafeAreaProvider,
11
- ScreenLayout,
12
- ScreenHeader,
13
- AtomicButton,
14
- AtomicText
15
- } from '../../index';
16
-
17
- // 1. Wrap your app root with SafeAreaProvider
18
- export function App() {
19
- return (
20
- <SafeAreaProvider>
21
- <View />
22
- </SafeAreaProvider>
23
- );
24
- }
25
-
26
- // 2. Use ScreenLayout in your screens
27
- export function HomeScreen() {
28
- return (
29
- <ScreenLayout
30
- // Safe area edges - default is ['top']
31
- edges={['top']}
32
- // Enable scrolling - default is true
33
- scrollable={true}
34
- // Optional header
35
- header={
36
- <ScreenHeader
37
- title="Home"
38
- />
39
- }
40
- // Optional footer
41
- footer={
42
- <View style={{ padding: 16 }}>
43
- <AtomicButton onPress={() => console.log('Action')}>
44
- Action Button
45
- </AtomicButton>
46
- </View>
47
- }
48
- >
49
- <AtomicText type="headlineLarge">Welcome to Home</AtomicText>
50
- <AtomicText type="bodyMedium">
51
- This screen uses ScreenLayout with default safe area configuration.
52
- </AtomicText>
53
- </ScreenLayout>
54
- );
55
- }
56
-
57
- // 3. Modal screen example with different safe area edges
58
- export function ModalScreen() {
59
- return (
60
- <ScreenLayout
61
- // Full safe area for modals
62
- edges={['top', 'bottom']}
63
- scrollable={false}
64
- >
65
- <AtomicText type="headlineMedium">Modal Content</AtomicText>
66
- </ScreenLayout>
67
- );
68
- }
69
-
70
- // 4. Screen with custom scroll behavior
71
- export function CustomScrollScreen() {
72
- return (
73
- <ScreenLayout scrollable={false}>
74
- {/* Your custom scroll component */}
75
- <View />
76
- </ScreenLayout>
77
- );
78
- }
79
-
80
- // 5. Using safe area hooks directly
81
- import { useContentSafeAreaPadding, useSafeAreaInsets } from '../../index';
82
-
83
- export function CustomComponent() {
84
- const insets = useSafeAreaInsets();
85
- const { paddingBottom } = useContentSafeAreaPadding();
86
-
87
- return (
88
- <View style={{ paddingTop: insets.top, paddingBottom }}>
89
- <Text>Custom Safe Area Usage</Text>
90
- </View>
91
- );
92
- }
@@ -1,120 +0,0 @@
1
- /**
2
- * Card Multimedia Types
3
- * Multimedia support for flashcard functionality
4
- */
5
-
6
- export type CardMediaType = "image" | "audio" | "video";
7
- export type CardMediaPosition = "front" | "back" | "both";
8
-
9
- export interface CardMediaAttachment {
10
- id: string;
11
- type: CardMediaType;
12
- position: CardMediaPosition;
13
- url: string;
14
- localPath?: string;
15
- filename: string;
16
- fileSize: number;
17
- mimeType: string;
18
- duration?: number; // For audio/video in seconds
19
- thumbnailUrl?: string; // For videos
20
- caption?: string;
21
- isDownloaded: boolean;
22
- createdAt: string;
23
- }
24
-
25
- export interface CardMultimediaFlashcard {
26
- id: string;
27
- front: string;
28
- back: string;
29
- difficulty: "easy" | "medium" | "hard";
30
- tags: string[];
31
- createdAt?: string;
32
- updatedAt?: string;
33
- // Extended properties for multimedia support
34
- media: CardMediaAttachment[];
35
- hasMedia: boolean; // Computed property
36
- mediaType: CardMediaType[]; // Array of media types present
37
- isDownloaded: boolean; // All media downloaded?
38
- estimatedSize: number; // Total size in bytes
39
- }
40
-
41
- export interface CardMediaGenerationRequest {
42
- type: "text_to_image" | "text_to_audio" | "image_search";
43
- input: {
44
- text?: string;
45
- prompt?: string;
46
- language?: string;
47
- voice?: "male" | "female" | "neutral";
48
- style?: "realistic" | "cartoon" | "artistic";
49
- };
50
- options: {
51
- maxResults?: number;
52
- quality?: "low" | "medium" | "high";
53
- format?: "jpeg" | "png" | "mp3" | "wav";
54
- };
55
- }
56
-
57
- export interface CardMediaGenerationResult {
58
- success: boolean;
59
- attachments: CardMediaAttachment[];
60
- creditsUsed: number;
61
- processingTime: number;
62
- error?: string;
63
- requestId: string;
64
- }
65
-
66
- export interface CardMediaUploadProgress {
67
- fileId: string;
68
- progress: number; // 0-100
69
- status: "uploading" | "processing" | "completed" | "error";
70
- error?: string;
71
- url?: string;
72
- }
73
-
74
- export interface CardMediaCompressionOptions {
75
- quality: number; // 0.1 - 1.0
76
- maxWidth?: number;
77
- maxHeight?: number;
78
- maxFileSize?: number; // bytes
79
- format?: "jpeg" | "png" | "webp";
80
- }
81
-
82
- export interface CardMediaFile {
83
- name: string;
84
- type: string;
85
- size: number;
86
- uri?: string;
87
- }
88
-
89
- export interface CreateCardMultimediaData {
90
- front: string;
91
- back: string;
92
- difficulty?: "easy" | "medium" | "hard";
93
- tags?: string[];
94
- media?: CardMediaAttachment[];
95
- }
96
-
97
- export interface CardMediaValidation {
98
- isValid: boolean;
99
- errors: string[];
100
- warnings: string[];
101
- recommendations: string[];
102
- }
103
-
104
- export interface CardMultimediaFlashcardService {
105
- uploadMedia(
106
- file: CardMediaFile,
107
- options?: CardMediaCompressionOptions,
108
- ): Promise<CardMediaAttachment>;
109
- generateMedia(
110
- request: CardMediaGenerationRequest,
111
- ): Promise<CardMediaGenerationResult>;
112
- validateMedia(file: CardMediaFile): Promise<CardMediaValidation>;
113
- optimizeMedia(
114
- attachment: CardMediaAttachment,
115
- options: CardMediaCompressionOptions,
116
- ): Promise<CardMediaAttachment>;
117
- deleteMedia(attachmentId: string): Promise<void>;
118
- getMediaUrl(attachmentId: string): Promise<string>;
119
- downloadMedia(attachmentId: string): Promise<string>; // Returns local path
120
- }
@@ -1,99 +0,0 @@
1
- # CardMediaGenerationService
2
-
3
- ## Purpose
4
- Service that performs AI-based media generation operations for flashcards, including text-to-image, text-to-audio, and image-search capabilities.
5
-
6
- ## File Location
7
- `/Users/umituz/Desktop/github/umituz/apps/artificial_intelligence/npm-packages/react-native-media/src/infrastructure/services/CardMediaGenerationService`
8
-
9
- ## Strategy
10
- - Generate media content using AI APIs for card applications
11
- - Support multiple generation types (text-to-image, text-to-audio, image-search)
12
- - Track processing time and credit/balance usage
13
- - Return card-compatible media attachments with position support
14
- - Provide detailed result information including success status and error messages
15
- - Enable batch generation with multiple results
16
- - Maintain unique request IDs for tracking and debugging
17
-
18
- ## Forbidden
19
- - **DO NOT** generate media without checking available credits/balance
20
- - **DO NOT** use empty or null prompts for generation
21
- - **DO NOT** assume all generation requests will succeed
22
- - **DO NOT** ignore generation timeout limits
23
- - **DO NOT** generate inappropriate or copyrighted content
24
- - **DO NOT** proceed without error handling for API failures
25
- - **DO NOT** mix generation types in single requests
26
- - **DO NOT** bypass request ID tracking
27
-
28
- ## Rules
29
- 1. All generation operations must include a valid prompt
30
- 2. Text-to-image generation requires prompt and optional style/maxResults
31
- 3. Text-to-audio generation requires prompt, language, and optional voice/speed
32
- 4. Image search requires keyword prompt and optional maxResults
33
- 5. Credit costs vary by type: text-to-image (5), text-to-audio (3), image-search (2)
34
- 6. All generated media must have position attribute set to 'both' by default
35
- 7. Processing time must be tracked and returned in milliseconds
36
- 8. Unique request IDs must be generated for each operation
37
- 9. Generation failures must return clear error messages
38
- 10. Audio files must be assigned a 10-second duration by default
39
- 11. maxResults defaults to 1 for text-to-image, 5 for image-search
40
-
41
- ## AI Agent Guidelines
42
-
43
- When working with CardMediaGenerationService:
44
-
45
- 1. **Pre-generation Checks**: Always verify credit/balance before generation requests
46
- 2. **Prompt Quality**: Use clear, descriptive prompts for better results
47
- 3. **Type Selection**: Choose appropriate generation type for use case
48
- 4. **Result Validation**: Always check success flag before using results
49
- 5. **Error Handling**: Handle API failures, timeouts, and insufficient credits
50
- 6. **Position Assignment**: Set correct position (front/back/both) for card use
51
- 7. **Request Tracking**: Store request IDs for debugging and support
52
-
53
- ### Generation Type Guidelines
54
-
55
- - **Text-to-Image**: Use for visual content on cards (front typically)
56
- - Specify style (realistic, artistic) for better results
57
- - Set maxResults to 1 unless multiple options needed
58
- - Images receive position='both' by default
59
-
60
- - **Text-to-Audio**: Use for pronunciation or audio explanations
61
- - Specify language code (tr-TR, en-US, etc.)
62
- - Set voice type (male, female) if applicable
63
- - Adjust speed (0.5-2.0) for playback preferences
64
- - Audio receives 10-second duration by default
65
-
66
- - **Image Search**: Use for finding relevant visuals
67
- - Use specific keywords for better results
68
- - Set maxResults for multiple options
69
- - Credits are cheaper than text-to-image
70
-
71
- ### Credit Management
72
-
73
- - Calculate total credits before batch operations
74
- - Text-to-image: 5 credits per request
75
- - Text-to-audio: 3 credits per request
76
- - Image search: 2 credits per request
77
- - Handle insufficient credit errors gracefully
78
- - Track credits used from generation results
79
-
80
- ### Error Handling Patterns
81
-
82
- - Check success flag before accessing attachments
83
- - Parse error messages for specific failure types:
84
- - "insufficient credits" - balance too low
85
- - "timeout" - operation took too long
86
- - "invalid prompt" - prompt validation failed
87
- - "api error" - underlying API failure
88
-
89
- ### Performance Considerations
90
-
91
- - Generation operations are simulated (3 seconds delay)
92
- - Batch multiple results in single request when possible
93
- - Track processing time for performance monitoring
94
- - Use request IDs for debugging slow operations
95
-
96
- ## Dependencies
97
- - CardMediaAttachment type from domain layer
98
- - AI generation APIs (simulated in development)
99
- - Credit/balance management system
@@ -1,101 +0,0 @@
1
- /**
2
- * Card Media Generation Service
3
- * Handles AI media generation (text-to-image, text-to-audio, image-search)
4
- */
5
-
6
- import type {
7
- CardMediaAttachment,
8
- CardMediaGenerationRequest,
9
- CardMediaGenerationResult,
10
- CardMediaType,
11
- CardMediaPosition,
12
- } from "../../domain/entities/CardMultimedia.types";
13
-
14
- export class CardMediaGenerationService {
15
- /**
16
- * Generate media from AI (text-to-image, text-to-audio, etc.)
17
- */
18
- async generateMedia(
19
- request: CardMediaGenerationRequest,
20
- ): Promise<CardMediaGenerationResult> {
21
- try {
22
- const startTime = Date.now();
23
-
24
- // Simulate AI generation
25
- await new Promise((resolve) => setTimeout(resolve, 3000));
26
-
27
- const attachments: CardMediaAttachment[] = [];
28
-
29
- switch (request.type) {
30
- case "text_to_image":
31
- for (let i = 0; i < (request.options.maxResults || 1); i++) {
32
- attachments.push({
33
- id: `ai_img_${Date.now()}_${i}`,
34
- type: "image" as CardMediaType,
35
- position: "both" as CardMediaPosition,
36
- url: `https://picsum.photos/400/300?random=${Date.now() + i}`,
37
- filename: `ai_generated_${i}.jpg`,
38
- fileSize: 150000, // 150KB
39
- mimeType: "image/jpeg",
40
- isDownloaded: false,
41
- createdAt: new Date().toISOString(),
42
- });
43
- }
44
- break;
45
-
46
- case "text_to_audio":
47
- attachments.push({
48
- id: `ai_audio_${Date.now()}`,
49
- type: "audio" as CardMediaType,
50
- position: "back" as CardMediaPosition,
51
- url: `https://example.com/audio_${Date.now()}.mp3`,
52
- filename: `ai_generated_${Date.now()}.mp3`,
53
- fileSize: 80000, // 80KB
54
- mimeType: "audio/mp3",
55
- duration: 10, // 10 seconds
56
- isDownloaded: false,
57
- createdAt: new Date().toISOString(),
58
- });
59
- break;
60
-
61
- case "image_search":
62
- for (let i = 0; i < (request.options.maxResults || 5); i++) {
63
- attachments.push({
64
- id: `search_img_${Date.now()}_${i}`,
65
- type: "image" as CardMediaType,
66
- position: "both" as CardMediaPosition,
67
- url: `https://picsum.photos/400/300?random=${Date.now() + i}`,
68
- filename: `search_result_${i}.jpg`,
69
- fileSize: 120000, // 120KB
70
- mimeType: "image/jpeg",
71
- isDownloaded: false,
72
- createdAt: new Date().toISOString(),
73
- });
74
- }
75
- break;
76
- }
77
-
78
- return {
79
- success: true,
80
- attachments,
81
- creditsUsed:
82
- request.type === "text_to_image"
83
- ? 5
84
- : request.type === "text_to_audio"
85
- ? 3
86
- : 2,
87
- processingTime: Date.now() - startTime,
88
- requestId: `req_${Date.now()}`,
89
- };
90
- } catch (error) {
91
- return {
92
- success: false,
93
- attachments: [],
94
- creditsUsed: 0,
95
- processingTime: 0,
96
- error: error instanceof Error ? error.message : "Unknown error",
97
- requestId: "",
98
- };
99
- }
100
- }
101
- }