@onairos/react-native 3.7.2 → 3.7.3
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/lib/commonjs/api/index.js +219 -9
- package/lib/commonjs/components/BodyText.js +27 -9
- package/lib/commonjs/components/BrandMark.js +111 -10
- package/lib/commonjs/components/CodeInput.js +116 -9
- package/lib/commonjs/components/EmailInput.js +30 -8
- package/lib/commonjs/components/GoogleButton.js +56 -9
- package/lib/commonjs/components/HeadingGroup.js +43 -9
- package/lib/commonjs/components/LLMDataInputModal.js +664 -14
- package/lib/commonjs/components/ModalHeader.js +99 -9
- package/lib/commonjs/components/ModalSheet.js +47 -9
- package/lib/commonjs/components/Onairos.js +380 -14
- package/lib/commonjs/components/OnairosButton.js +313 -13
- package/lib/commonjs/components/OnairosSignInButton.js +130 -12
- package/lib/commonjs/components/Overlay.js +465 -13
- package/lib/commonjs/components/PersonaImage.js +137 -10
- package/lib/commonjs/components/PersonaLoadingScreen.js +318 -12
- package/lib/commonjs/components/PersonalizationConsentScreen.js +467 -13
- package/lib/commonjs/components/PinCreationScreen.js +403 -12
- package/lib/commonjs/components/PinInput.js +464 -9
- package/lib/commonjs/components/PlatformConnectorsStep.js +1311 -23
- package/lib/commonjs/components/PlatformList.js +137 -10
- package/lib/commonjs/components/PlatformToggle.js +180 -9
- package/lib/commonjs/components/PrimaryButton.js +180 -10
- package/lib/commonjs/components/SignInMatchAnimation.js +197 -9
- package/lib/commonjs/components/SignInStep.js +345 -12
- package/lib/commonjs/components/UniversalOnboarding.js +2780 -30
- package/lib/commonjs/components/VerificationStep.js +176 -11
- package/lib/commonjs/components/WelcomeScreen.js +461 -22
- package/lib/commonjs/components/icons/Basicproficon.js +37 -8
- package/lib/commonjs/components/icons/Basicprofile.js +21 -8
- package/lib/commonjs/components/icons/Checkbox.js +21 -8
- package/lib/commonjs/components/icons/Checkmark.js +27 -8
- package/lib/commonjs/components/icons/Contentanalysis.js +21 -8
- package/lib/commonjs/components/icons/Contenticon.js +39 -8
- package/lib/commonjs/components/icons/EnochE.js +41 -8
- package/lib/commonjs/components/icons/Personalityicon.js +30 -8
- package/lib/commonjs/components/icons/Personalityprofile.js +21 -8
- package/lib/commonjs/components/icons/Personalitytraits.js +21 -8
- package/lib/commonjs/components/icons/Userpreferences.js +21 -8
- package/lib/commonjs/components/icons/index.js +84 -17
- package/lib/commonjs/components/onboarding/OAuthWebView.js +1754 -18
- package/lib/commonjs/components/onboarding/OnboardingHeader.js +74 -10
- package/lib/commonjs/components/onboarding/PinInput.js +283 -10
- package/lib/commonjs/components/onboarding/PlatformConnector.js +249 -11
- package/lib/commonjs/config/PLATFORM_APIS.md +849 -0
- package/lib/commonjs/config/api.js +56 -7
- package/lib/commonjs/constants/index.js +120 -7
- package/lib/commonjs/context/AuthContext.js +345 -10
- package/lib/commonjs/hooks/useConnectedAccounts.js +111 -9
- package/lib/commonjs/hooks/useConnections.js +102 -8
- package/lib/commonjs/hooks/useCredentials.js +178 -10
- package/lib/commonjs/hooks/useUserConnections.js +148 -10
- package/lib/commonjs/index.js +439 -34
- package/lib/commonjs/services/apiClient.js +298 -8
- package/lib/commonjs/services/biometricPinService.js +180 -8
- package/lib/commonjs/services/chatGPTConversationExtractor.js +155 -8
- package/lib/commonjs/services/chatGPTConversationService.js +275 -9
- package/lib/commonjs/services/claudeConversationExtractor.js +103 -8
- package/lib/commonjs/services/claudeConversationService.js +158 -9
- package/lib/commonjs/services/connectedAccountsService.js +310 -10
- package/lib/commonjs/services/googleAuthService.js +252 -11
- package/lib/commonjs/services/hingeDataExtractor.js +105 -8
- package/lib/commonjs/services/hingeDataService.js +150 -9
- package/lib/commonjs/services/imageCompressionService.js +260 -7
- package/lib/commonjs/services/instagramDataExtractor.js +126 -8
- package/lib/commonjs/services/instagramDataService.js +163 -9
- package/lib/commonjs/services/jwtStorageService.js +276 -7
- package/lib/commonjs/services/linkedinDOMExtractor.js +245 -7
- package/lib/commonjs/services/linkedinProfileService.js +222 -9
- package/lib/commonjs/services/linkedinScrapingService.js +230 -8
- package/lib/commonjs/services/llmDataStorage.js +294 -8
- package/lib/commonjs/services/mobileTrainingService.js +186 -8
- package/lib/commonjs/services/netflixDataExtractor.js +120 -8
- package/lib/commonjs/services/netflixDataService.js +198 -9
- package/lib/commonjs/services/pinEncryptionService.js +84 -8
- package/lib/commonjs/services/pinStorageUtils.js +105 -7
- package/lib/commonjs/services/platformAuthService.js +1484 -12
- package/lib/commonjs/services/sephoraDataExtractor.js +140 -8
- package/lib/commonjs/services/sephoraDataService.js +200 -9
- package/lib/commonjs/services/spotifyDataExtractor.js +148 -8
- package/lib/commonjs/services/spotifyDataService.js +241 -9
- package/lib/commonjs/services/storageService.js +404 -8
- package/lib/commonjs/services/telegramDataExtractor.js +115 -8
- package/lib/commonjs/services/telegramDataService.js +499 -9
- package/lib/commonjs/services/trainingApiHelpers.js +73 -7
- package/lib/commonjs/services/userConnectionsService.js +340 -10
- package/lib/commonjs/services/youtubeMigrationService.js +416 -10
- package/lib/commonjs/theme/index.js +250 -7
- package/lib/commonjs/types/ambient.d.js +2 -1
- package/lib/commonjs/types/declarations.d.js +2 -1
- package/lib/commonjs/types/index.js +6 -1
- package/lib/commonjs/types/node-fix.d.js +2 -1
- package/lib/commonjs/types/node-override.d.js +2 -1
- package/lib/commonjs/types/opacity.d.js +2 -1
- package/lib/commonjs/types.js +14 -1
- package/lib/commonjs/utils/Portal.js +98 -8
- package/lib/commonjs/utils/api.js +130 -9
- package/lib/commonjs/utils/assetRegistry.js +210 -35
- package/lib/commonjs/utils/auth.js +112 -9
- package/lib/commonjs/utils/connectorTests.js +613 -29
- package/lib/commonjs/utils/crypto.js +62 -8
- package/lib/commonjs/utils/debugHelper.js +64 -1
- package/lib/commonjs/utils/encryption.js +76 -7
- package/lib/commonjs/utils/eventUtils.js +288 -1
- package/lib/commonjs/utils/haptics.js +66 -9
- package/lib/commonjs/utils/imagePreloader.js +6 -1
- package/lib/commonjs/utils/networkDiagnostics.js +226 -8
- package/lib/commonjs/utils/onairosApi.js +350 -9
- package/lib/commonjs/utils/programmaticFlow.js +117 -9
- package/lib/commonjs/utils/retryHelper.js +220 -1
- package/lib/commonjs/utils/secureStorage.js +349 -10
- package/lib/commonjs/utils/webviewScripts/chatgpt.js +551 -1
- package/lib/commonjs/utils/webviewScripts/claude.js +376 -1
- package/lib/commonjs/utils/webviewScripts/hinge.js +411 -1
- package/lib/commonjs/utils/webviewScripts/index.js +698 -15
- package/lib/commonjs/utils/webviewScripts/instagram.js +454 -1
- package/lib/commonjs/utils/webviewScripts/linkedin.js +880 -1
- package/lib/commonjs/utils/webviewScripts/netflix.js +382 -1
- package/lib/commonjs/utils/webviewScripts/sephora.js +516 -1
- package/lib/commonjs/utils/webviewScripts/spotify.js +419 -1
- package/lib/commonjs/utils/webviewScripts/telegram.js +678 -1
- package/lib/module/api/index.js +211 -1
- package/lib/module/components/BodyText.js +20 -1
- package/lib/module/components/BrandMark.js +104 -1
- package/lib/module/components/CodeInput.js +109 -1
- package/lib/module/components/EmailInput.js +23 -1
- package/lib/module/components/GoogleButton.js +49 -1
- package/lib/module/components/HeadingGroup.js +36 -1
- package/lib/module/components/LLMDataInputModal.js +656 -7
- package/lib/module/components/ModalHeader.js +92 -1
- package/lib/module/components/ModalSheet.js +39 -1
- package/lib/module/components/Onairos.js +373 -1
- package/lib/module/components/OnairosButton.js +305 -1
- package/lib/module/components/OnairosSignInButton.js +121 -1
- package/lib/module/components/Overlay.js +456 -1
- package/lib/module/components/PersonaImage.js +129 -1
- package/lib/module/components/PersonaLoadingScreen.js +310 -1
- package/lib/module/components/PersonalizationConsentScreen.js +460 -1
- package/lib/module/components/PinCreationScreen.js +396 -1
- package/lib/module/components/PinInput.js +456 -1
- package/lib/module/components/PlatformConnectorsStep.js +1302 -6
- package/lib/module/components/PlatformList.js +129 -1
- package/lib/module/components/PlatformToggle.js +173 -1
- package/lib/module/components/PrimaryButton.js +172 -1
- package/lib/module/components/SignInMatchAnimation.js +189 -1
- package/lib/module/components/SignInStep.js +338 -1
- package/lib/module/components/UniversalOnboarding.js +2770 -1
- package/lib/module/components/VerificationStep.js +168 -1
- package/lib/module/components/WelcomeScreen.js +453 -1
- package/lib/module/components/icons/Basicproficon.js +30 -1
- package/lib/module/components/icons/Basicprofile.js +14 -1
- package/lib/module/components/icons/Checkbox.js +14 -1
- package/lib/module/components/icons/Checkmark.js +20 -1
- package/lib/module/components/icons/Contentanalysis.js +14 -1
- package/lib/module/components/icons/Contenticon.js +32 -1
- package/lib/module/components/icons/EnochE.js +34 -1
- package/lib/module/components/icons/Personalityicon.js +23 -1
- package/lib/module/components/icons/Personalityprofile.js +14 -1
- package/lib/module/components/icons/Personalitytraits.js +14 -1
- package/lib/module/components/icons/Userpreferences.js +14 -1
- package/lib/module/components/icons/index.js +13 -1
- package/lib/module/components/onboarding/OAuthWebView.js +1746 -1
- package/lib/module/components/onboarding/OnboardingHeader.js +66 -1
- package/lib/module/components/onboarding/PinInput.js +274 -1
- package/lib/module/components/onboarding/PlatformConnector.js +240 -1
- package/lib/module/config/PLATFORM_APIS.md +849 -0
- package/lib/module/config/api.js +47 -1
- package/lib/module/constants/index.js +114 -1
- package/lib/module/context/AuthContext.js +335 -1
- package/lib/module/hooks/useConnectedAccounts.js +106 -1
- package/lib/module/hooks/useConnections.js +95 -1
- package/lib/module/hooks/useCredentials.js +171 -6
- package/lib/module/hooks/useUserConnections.js +140 -1
- package/lib/module/index.js +172 -1
- package/lib/module/services/apiClient.js +295 -1
- package/lib/module/services/biometricPinService.js +169 -1
- package/lib/module/services/chatGPTConversationExtractor.js +149 -1
- package/lib/module/services/chatGPTConversationService.js +268 -1
- package/lib/module/services/claudeConversationExtractor.js +97 -1
- package/lib/module/services/claudeConversationService.js +151 -1
- package/lib/module/services/connectedAccountsService.js +293 -1
- package/lib/module/services/googleAuthService.js +241 -1
- package/lib/module/services/hingeDataExtractor.js +99 -1
- package/lib/module/services/hingeDataService.js +143 -1
- package/lib/module/services/imageCompressionService.js +250 -1
- package/lib/module/services/instagramDataExtractor.js +120 -1
- package/lib/module/services/instagramDataService.js +156 -1
- package/lib/module/services/jwtStorageService.js +257 -1
- package/lib/module/services/linkedinDOMExtractor.js +234 -1
- package/lib/module/services/linkedinProfileService.js +210 -1
- package/lib/module/services/linkedinScrapingService.js +219 -1
- package/lib/module/services/llmDataStorage.js +277 -1
- package/lib/module/services/mobileTrainingService.js +173 -1
- package/lib/module/services/netflixDataExtractor.js +114 -1
- package/lib/module/services/netflixDataService.js +191 -1
- package/lib/module/services/pinEncryptionService.js +74 -6
- package/lib/module/services/pinStorageUtils.js +93 -1
- package/lib/module/services/platformAuthService.js +1461 -1
- package/lib/module/services/sephoraDataExtractor.js +134 -1
- package/lib/module/services/sephoraDataService.js +193 -1
- package/lib/module/services/spotifyDataExtractor.js +142 -1
- package/lib/module/services/spotifyDataService.js +234 -1
- package/lib/module/services/storageService.js +383 -1
- package/lib/module/services/telegramDataExtractor.js +109 -1
- package/lib/module/services/telegramDataService.js +493 -1
- package/lib/module/services/trainingApiHelpers.js +67 -1
- package/lib/module/services/userConnectionsService.js +329 -1
- package/lib/module/services/youtubeMigrationService.js +405 -1
- package/lib/module/theme/index.js +245 -1
- package/lib/module/types.js +10 -1
- package/lib/module/utils/Portal.js +90 -1
- package/lib/module/utils/api.js +118 -1
- package/lib/module/utils/assetRegistry.js +200 -34
- package/lib/module/utils/auth.js +100 -1
- package/lib/module/utils/connectorTests.js +600 -27
- package/lib/module/utils/crypto.js +54 -1
- package/lib/module/utils/debugHelper.js +54 -1
- package/lib/module/utils/encryption.js +67 -1
- package/lib/module/utils/eventUtils.js +270 -1
- package/lib/module/utils/haptics.js +59 -8
- package/lib/module/utils/imagePreloader.js +3 -1
- package/lib/module/utils/networkDiagnostics.js +217 -1
- package/lib/module/utils/onairosApi.js +333 -1
- package/lib/module/utils/programmaticFlow.js +111 -1
- package/lib/module/utils/retryHelper.js +211 -1
- package/lib/module/utils/secureStorage.js +330 -6
- package/lib/module/utils/webviewScripts/chatgpt.js +545 -1
- package/lib/module/utils/webviewScripts/claude.js +370 -1
- package/lib/module/utils/webviewScripts/hinge.js +405 -1
- package/lib/module/utils/webviewScripts/index.js +434 -1
- package/lib/module/utils/webviewScripts/instagram.js +448 -1
- package/lib/module/utils/webviewScripts/linkedin.js +874 -1
- package/lib/module/utils/webviewScripts/netflix.js +376 -1
- package/lib/module/utils/webviewScripts/sephora.js +510 -1
- package/lib/module/utils/webviewScripts/spotify.js +413 -1
- package/lib/module/utils/webviewScripts/telegram.js +672 -1
- package/package.json +2 -2
|
@@ -1 +1,99 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Hinge Data Extractor
|
|
3
|
+
*
|
|
4
|
+
* Orchestrates the Hinge data export flow:
|
|
5
|
+
* 1. Receives extracted matches/chats from WebView
|
|
6
|
+
* 2. Validates and formats data
|
|
7
|
+
* 3. Sends to backend via hingeDataService
|
|
8
|
+
*
|
|
9
|
+
* This acts as the bridge between OAuthWebView and the backend API.
|
|
10
|
+
*
|
|
11
|
+
* @reference ChatGPT implementation: src/services/chatGPTConversationExtractor.ts
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { storeHingeData } from './hingeDataService';
|
|
15
|
+
import { Alert } from 'react-native';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Combined Hinge export data from WebView
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Hook for Hinge data extraction operations
|
|
23
|
+
*/
|
|
24
|
+
export const useHingeDataExtractor = () => {
|
|
25
|
+
/**
|
|
26
|
+
* Initiate data export to backend
|
|
27
|
+
*
|
|
28
|
+
* @param username - User identifier
|
|
29
|
+
* @param data - Extracted Hinge data (matches and chats)
|
|
30
|
+
* @returns true if successful, false otherwise
|
|
31
|
+
*/
|
|
32
|
+
const initiateDataExport = async (username, data) => {
|
|
33
|
+
var _data$chats;
|
|
34
|
+
console.log('🚀 [HINGE_EXTRACTOR] Initiating data export');
|
|
35
|
+
console.log('👤 [HINGE_EXTRACTOR] Username:', username);
|
|
36
|
+
console.log('📊 [HINGE_EXTRACTOR] Matches:', data.total_matches);
|
|
37
|
+
console.log('📊 [HINGE_EXTRACTOR] Chats:', data.total_chats);
|
|
38
|
+
console.log('📊 [HINGE_EXTRACTOR] Messages:', data.total_messages);
|
|
39
|
+
|
|
40
|
+
// Validation
|
|
41
|
+
if (!username) {
|
|
42
|
+
console.error('❌ [HINGE_EXTRACTOR] Username is required');
|
|
43
|
+
Alert.alert('Error', 'Username is required to export Hinge data.', [{
|
|
44
|
+
text: 'OK',
|
|
45
|
+
style: 'default'
|
|
46
|
+
}]);
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Handle empty data as success - user might be new
|
|
51
|
+
if ((!data.matches || data.matches.length === 0) && (!data.chats || data.chats.length === 0)) {
|
|
52
|
+
console.log('ℹ️ [HINGE_EXTRACTOR] No data to export - treating as success (connected)');
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Validate chat structure
|
|
57
|
+
const validChats = (data.chats || []).filter(chat => {
|
|
58
|
+
const isValid = chat.match_id && Array.isArray(chat.user_messages) && chat.user_messages.length > 0;
|
|
59
|
+
if (!isValid) {
|
|
60
|
+
console.warn('⚠️ [HINGE_EXTRACTOR] Invalid chat:', chat);
|
|
61
|
+
}
|
|
62
|
+
return isValid;
|
|
63
|
+
});
|
|
64
|
+
if (validChats.length < (((_data$chats = data.chats) === null || _data$chats === void 0 ? void 0 : _data$chats.length) || 0)) {
|
|
65
|
+
var _data$chats2;
|
|
66
|
+
console.warn(`⚠️ [HINGE_EXTRACTOR] Filtered out ${(((_data$chats2 = data.chats) === null || _data$chats2 === void 0 ? void 0 : _data$chats2.length) || 0) - validChats.length} invalid chats`);
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
console.log('📡 [HINGE_EXTRACTOR] Sending to backend...');
|
|
70
|
+
const result = await storeHingeData(username, {
|
|
71
|
+
matches: data.matches || [],
|
|
72
|
+
chats: validChats
|
|
73
|
+
});
|
|
74
|
+
if (result.success) {
|
|
75
|
+
console.log('✅ [HINGE_EXTRACTOR] Export completed successfully');
|
|
76
|
+
console.log('📊 [HINGE_EXTRACTOR] Backend response:', result.data);
|
|
77
|
+
return true;
|
|
78
|
+
} else {
|
|
79
|
+
console.error('❌ [HINGE_EXTRACTOR] Backend storage failed:', result.error);
|
|
80
|
+
Alert.alert('Export Failed', result.error || 'An unknown error occurred during data storage.', [{
|
|
81
|
+
text: 'OK',
|
|
82
|
+
style: 'default'
|
|
83
|
+
}]);
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
} catch (error) {
|
|
87
|
+
console.error('❌ [HINGE_EXTRACTOR] Unexpected error during export:', error);
|
|
88
|
+
Alert.alert('Export Error', 'Failed to connect to the data storage service. Please check your network connection.', [{
|
|
89
|
+
text: 'OK',
|
|
90
|
+
style: 'default'
|
|
91
|
+
}]);
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
return {
|
|
96
|
+
initiateDataExport
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
//# sourceMappingURL=hingeDataExtractor.js.map
|
|
@@ -1 +1,143 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Hinge Data Service
|
|
3
|
+
*
|
|
4
|
+
* API layer for storing Hinge data on backend.
|
|
5
|
+
* Sends extracted matches and chats to /platform-data/store endpoint.
|
|
6
|
+
*
|
|
7
|
+
* MATCHES ChatGPT implementation pattern
|
|
8
|
+
* - Sends data in batches
|
|
9
|
+
* - Uses format: { platform, data, metadata }
|
|
10
|
+
* - Platform: "mobile-hinge"
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { API_CONFIG } from '../config/api';
|
|
14
|
+
import AsyncStorage from '@react-native-async-storage/async-storage';
|
|
15
|
+
import { Platform } from 'react-native';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Structure of a single message in a chat
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Structure of chat data extracted from Hinge
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Structure of match data extracted from Hinge
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Combined Hinge data to store
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Response from backend endpoint
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Store Hinge data on backend
|
|
39
|
+
*
|
|
40
|
+
* @param userId - Username or identifier
|
|
41
|
+
* @param data - Hinge matches and chat data
|
|
42
|
+
* @returns Response indicating success/failure with metadata
|
|
43
|
+
*/
|
|
44
|
+
export const storeHingeData = async (userId, data) => {
|
|
45
|
+
console.log('🚀 [HINGE_SERVICE] Storing Hinge data for:', userId);
|
|
46
|
+
console.log('📊 [HINGE_SERVICE] Matches:', data.matches.length);
|
|
47
|
+
console.log('📊 [HINGE_SERVICE] Chats:', data.chats.length);
|
|
48
|
+
console.log('📊 [HINGE_SERVICE] Total user messages:', data.chats.reduce((sum, c) => sum + c.user_messages.length, 0));
|
|
49
|
+
|
|
50
|
+
// Input validation
|
|
51
|
+
if (!userId) {
|
|
52
|
+
console.error('❌ [HINGE_SERVICE] Invalid input: userId missing');
|
|
53
|
+
return {
|
|
54
|
+
success: false,
|
|
55
|
+
error: 'Invalid input: userId missing.'
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
try {
|
|
59
|
+
// Get auth token - check all possible storage keys
|
|
60
|
+
const authToken = (await AsyncStorage.getItem('onairos_jwt_token')) || (await AsyncStorage.getItem('enoch_token')) || (await AsyncStorage.getItem('auth_token'));
|
|
61
|
+
if (!authToken) {
|
|
62
|
+
console.error('❌ [HINGE_SERVICE] No auth token found');
|
|
63
|
+
return {
|
|
64
|
+
success: false,
|
|
65
|
+
error: 'Authentication token not found. Please log in again.'
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
console.log('🔑 [HINGE_SERVICE] Auth token found');
|
|
69
|
+
|
|
70
|
+
// Mobile metadata
|
|
71
|
+
const mobileMetadata = {
|
|
72
|
+
platform: Platform.OS,
|
|
73
|
+
appVersion: '1.0.0',
|
|
74
|
+
osVersion: Platform.OS === 'ios' ? '17.0' : Platform.OS,
|
|
75
|
+
deviceModel: Platform.OS === 'ios' ? 'iPhone' : 'Android',
|
|
76
|
+
isOfflineSync: false,
|
|
77
|
+
extractedAt: new Date().toISOString()
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
// Build request body
|
|
81
|
+
const requestBody = {
|
|
82
|
+
platform: 'mobile-hinge',
|
|
83
|
+
dataType: 'dating',
|
|
84
|
+
data: {
|
|
85
|
+
matches: data.matches,
|
|
86
|
+
chats: data.chats.map(chat => ({
|
|
87
|
+
matchId: chat.match_id,
|
|
88
|
+
matchName: chat.match_name,
|
|
89
|
+
messages: chat.user_messages.map((msg, idx) => ({
|
|
90
|
+
id: `${chat.match_id}-msg-${idx}`,
|
|
91
|
+
content: msg.content,
|
|
92
|
+
timestamp: msg.timestamp || new Date().toISOString(),
|
|
93
|
+
role: 'user'
|
|
94
|
+
})),
|
|
95
|
+
totalMessages: chat.total_messages
|
|
96
|
+
}))
|
|
97
|
+
},
|
|
98
|
+
summary: {
|
|
99
|
+
matchCount: data.matches.length,
|
|
100
|
+
chatCount: data.chats.length,
|
|
101
|
+
totalUserMessages: data.chats.reduce((sum, c) => sum + c.user_messages.length, 0)
|
|
102
|
+
},
|
|
103
|
+
mobileMetadata: mobileMetadata
|
|
104
|
+
};
|
|
105
|
+
console.log('📡 [HINGE_SERVICE] Sending to backend...');
|
|
106
|
+
console.log('📍 [HINGE_SERVICE] URL:', `${API_CONFIG.BASE_URL}/platform-data/store`);
|
|
107
|
+
const response = await fetch(`${API_CONFIG.BASE_URL}/platform-data/store`, {
|
|
108
|
+
method: 'POST',
|
|
109
|
+
headers: {
|
|
110
|
+
'Content-Type': 'application/json',
|
|
111
|
+
'Authorization': `Bearer ${authToken}`,
|
|
112
|
+
'User-Agent': `OnairosSDK/1.0.0 (${Platform.OS})`
|
|
113
|
+
},
|
|
114
|
+
body: JSON.stringify(requestBody)
|
|
115
|
+
});
|
|
116
|
+
const responseData = await response.json();
|
|
117
|
+
if (response.ok) {
|
|
118
|
+
console.log('✅ [HINGE_SERVICE] Successfully stored Hinge data');
|
|
119
|
+
if (responseData.message) {
|
|
120
|
+
console.log(`📝 [HINGE_SERVICE] Backend response: ${responseData.message}`);
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
success: true,
|
|
124
|
+
message: responseData.message || 'Hinge data stored successfully',
|
|
125
|
+
data: responseData.data
|
|
126
|
+
};
|
|
127
|
+
} else {
|
|
128
|
+
console.warn(`⚠️ [HINGE_SERVICE] Backend returned status: ${response.status}`);
|
|
129
|
+
console.warn(`⚠️ [HINGE_SERVICE] Error: ${responseData.error || 'Unknown error'}`);
|
|
130
|
+
return {
|
|
131
|
+
success: false,
|
|
132
|
+
error: responseData.error || `HTTP ${response.status}`
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
} catch (error) {
|
|
136
|
+
console.error('❌ [HINGE_SERVICE] Network error:', error);
|
|
137
|
+
return {
|
|
138
|
+
success: false,
|
|
139
|
+
error: error.message || 'Network error. Please check your connection.'
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
//# sourceMappingURL=hingeDataService.js.map
|
|
@@ -1 +1,250 @@
|
|
|
1
|
-
function _0x3d4a(_0x4ca2e0,_0x3d4a04){_0x4ca2e0=_0x4ca2e0-0x0;const _0x2eae13=_0x4ca2();let _0x51c158=_0x2eae13[_0x4ca2e0];return _0x51c158;}import _0x42342f from'@bam.tech/react-native-image-resizer';const getFileSizeFromUri=async _0x3c267c=>{const _0x385075={'zbbmO':function(_0x3e5d50,_0x10a223){return _0x3e5d50/_0x10a223;},'XVgiO':function(_0x4c2f7c,_0x2e6040){return _0x4c2f7c>_0x2e6040;},'MmnhA':function(_0x1c292d,_0x39255b){return _0x1c292d*_0x39255b;},'kYews':_0x3d4a(0x0),'aWLVs':_0x3d4a(0x1)};try{if(_0x385075[_0x3d4a(0x2)]!=='oxQts'){const _0x60f4ca=_0x385075[_0x3d4a(0x3)](_0x300438,_0x4fae69);if(_0x385075['XVgiO'](_0x60f4ca,0x2))_0x4015cb*=0.6,_0x5c8fdc=_0x352ad5[_0x3d4a(0x4)](_0x385075[_0x3d4a(0x5)](_0x510a42,0.8)),_0x57670a=_0x59df9b[_0x3d4a(0x4)](_0x31b1e3*0.8);else _0x60f4ca>1.5?(_0x5e99e9*=0.75,_0x2b3adc=_0x5abadf[_0x3d4a(0x4)](_0x2f9a5a*0.9),_0x3876bf=_0x2b6c9f[_0x3d4a(0x4)](_0x385075[_0x3d4a(0x5)](_0xde9c,0.9))):_0xa87fc6*=0.85;_0x54fcba=_0x3d2342['max'](0.1,_0xd97d4f),_0x1d1f01=_0x1391a6[_0x3d4a(0x6)](0x190,_0xcd9949),_0x1c2f9f=_0x2e6b19[_0x3d4a(0x6)](0x190,_0x14b3e5);}else{const _0x40755b=await fetch(_0x3c267c),_0x12eea8=await _0x40755b[_0x3d4a(0x7)]();return _0x12eea8[_0x3d4a(0x8)];}}catch(_0x27e64a){return _0x3d4a(0x9)===_0x3d4a(0x9)?(console[_0x3d4a(0xa)](_0x385075[_0x3d4a(0xb)],_0x27e64a),0x0):{'success':!![],'base64':_0x2dfc5f,'sizeKB':_0x44257a,'originalSizeKB':_0x4f1e30,'compressionRatio':0x1};}},imageToBase64=async _0x2a78b9=>{const _0x5139dc={'wcshz':function(_0x480550,_0x3a9d17){return _0x480550===_0x3a9d17;},'ZyEvt':_0x3d4a(0xc),'JGVCw':function(_0x326695,_0x55aea8){return _0x326695(_0x55aea8);},'GoIIe':function(_0x37074b,_0x3ee7e6){return _0x37074b!==_0x3ee7e6;},'HkHrp':'EDGgW','zltzw':function(_0x351903,_0x1013ca,_0x5a3eeb){return _0x351903(_0x1013ca,_0x5a3eeb);},'uKOhR':_0x3d4a(0xd),'WexEr':function(_0x24913c,_0x494942){return _0x24913c!==_0x494942;},'xEhmV':_0x3d4a(0xe),'RBwZV':'QBGIR','OVANF':_0x3d4a(0xf),'gWaNZ':_0x3d4a(0x10),'pqtMv':_0x3d4a(0x11),'JZShQ':_0x3d4a(0x12),'qwgEa':_0x3d4a(0x13)};try{if(_0x5139dc['pqtMv']!==_0x5139dc[_0x3d4a(0x14)]){const _0x2ddfe4=await fetch(_0x2a78b9),_0x437670=await _0x2ddfe4[_0x3d4a(0x7)]();return new Promise((_0x18eebe,_0x1a6803)=>{const _0x5541a6={'mbzkF':_0x3d4a(0x13),'Ogfza':function(_0x2c069c,_0x4c6380,_0x515198){return _0x5139dc['zltzw'](_0x2c069c,_0x4c6380,_0x515198);},'QFJgK':_0x5139dc['uKOhR']};if(_0x5139dc[_0x3d4a(0x15)](_0x5139dc['xEhmV'],_0x5139dc[_0x3d4a(0x16)])){const _0x3e5dce=new FileReader();_0x3e5dce['onloadend']=()=>{if(_0x5139dc[_0x3d4a(0x17)](_0x3d4a(0xc),_0x5139dc[_0x3d4a(0x18)]))try{const _0x58ccc6=_0x3e5dce[_0x3d4a(0x19)],_0x5abef3=_0x58ccc6['split'](',')[0x1];_0x5139dc[_0x3d4a(0x1a)](_0x18eebe,_0x5abef3);}catch(_0x26d313){if(_0x5139dc[_0x3d4a(0x1b)](_0x3d4a(0x1c),_0x5139dc[_0x3d4a(0x1d)]))_0x5139dc['JGVCw'](_0x1a6803,_0x26d313);else return _0x511469[_0x3d4a(0xa)](_0x5541a6['mbzkF'],_0xfd165f),null;}else return _0x5541a6['Ogfza'](_0x379867,_0x2b7e60,{'maxSizeKB':_0x5769ed,'maxWidth':0x4b0,'maxHeight':0x4b0,'quality':0.8,'format':_0x5541a6[_0x3d4a(0x1e)]});},_0x3e5dce[_0x3d4a(0x1f)]=_0x1a6803,_0x3e5dce[_0x3d4a(0x20)](_0x437670);}else try{const _0x29f8f3=_0x35d8a0['result'],_0x30862d=_0x29f8f3[_0x3d4a(0x21)](',')[0x1];_0xdc2e1c(_0x30862d);}catch(_0xe072a3){_0xaae8a(_0xe072a3);}});}else return _0x1f096c[_0x3d4a(0xa)](_0x5139dc['OVANF'],_0x40b312),{'success':![],'error':_0x4b08f4 instanceof _0x8876f9?_0x2ac482[_0x3d4a(0x22)]:_0x5139dc[_0x3d4a(0x23)],'originalSizeKB':0x0};}catch(_0x174071){return console[_0x3d4a(0xa)](_0x5139dc[_0x3d4a(0x24)],_0x174071),null;}};export const compressImageToTarget=async(_0x44404a,_0x553374={})=>{const _0x582195={'LwTuq':function(_0x5afda5,_0x5321a4){return _0x5afda5(_0x5321a4);},'IffPN':_0x3d4a(0x25),'dQjDs':function(_0x70f96f,_0x42227b){return _0x70f96f*_0x42227b;},'oPfRd':function(_0x1b9c4f,_0x15e4f7){return _0x1b9c4f*_0x15e4f7;},'WqFHG':function(_0x2deb24,_0x65cf0){return _0x2deb24/_0x65cf0;},'nZfBX':function(_0xad838f,_0x596c17){return _0xad838f+_0x596c17;},'oHObZ':_0x3d4a(0xd),'uMwFv':function(_0x24f6d9,_0x36618b){return _0x24f6d9/_0x36618b;},'KmSib':_0x3d4a(0x26),'SMBMn':function(_0x344cb3,_0x29e0f0){return _0x344cb3<=_0x29e0f0;},'BqgAx':_0x3d4a(0x27),'fKRjr':_0x3d4a(0x28),'EFESd':function(_0x41e0dc,_0x52dd81){return _0x41e0dc(_0x52dd81);},'cMIYU':'pyygh','RlqdF':function(_0x5c626e,_0x546e80){return _0x5c626e<_0x546e80;},'IXyGQ':function(_0x2fefc2,_0x480a67){return _0x2fefc2===_0x480a67;},'UxTEX':'DNfzg','Oqqtk':function(_0x2b45df,_0x1b77c9){return _0x2b45df(_0x1b77c9);},'IfNwT':function(_0x2f7c79,_0x2a4c87){return _0x2f7c79/_0x2a4c87;},'EOlSw':function(_0x22cde5,_0x549fdc){return _0x22cde5<=_0x549fdc;},'WUkkf':'✅\x20[COMPRESSION]\x20Target\x20size\x20achieved!','Obety':function(_0x4edbd7,_0x3af987){return _0x4edbd7/_0x3af987;},'bciIg':_0x3d4a(0x29),'HyyKR':function(_0x1f492d,_0xe6e3e8){return _0x1f492d>_0xe6e3e8;},'qzLHS':_0x3d4a(0x2a),'OXKzb':function(_0x4f65cf,_0x5458f1){return _0x4f65cf>_0x5458f1;},'izpkp':function(_0x3eecce,_0x1bfc7c){return _0x3eecce>_0x1bfc7c;},'PGHpW':function(_0x2a6418,_0x4fa2e9){return _0x2a6418*_0x4fa2e9;},'VFVpk':function(_0x23a89e,_0x349235){return _0x23a89e===_0x349235;},'jEfOm':_0x3d4a(0x2b),'zZRPK':_0x3d4a(0x2c),'NZtFS':function(_0x463ab7,_0x5bc11e){return _0x463ab7!==_0x5bc11e;},'JggDe':_0x3d4a(0x2d),'AxmNg':function(_0xa171ee,_0x16b18a){return _0xa171ee<_0x16b18a;},'dCtVC':_0x3d4a(0x2e),'HKXiE':'contain','viRMr':function(_0x1ed2d6,_0x2edcf4){return _0x1ed2d6/_0x2edcf4;},'NIhdx':_0x3d4a(0x2f),'KTxms':_0x3d4a(0xf),'rqcIt':function(_0x2251b4,_0x37c3cc){return _0x2251b4 instanceof _0x37c3cc;}},{maxSizeKB:maxSizeKB=0x12c,maxWidth:maxWidth=0x4b0,maxHeight:maxHeight=0x4b0,quality:quality=0.8,format:format=_0x582195[_0x3d4a(0x30)]}=_0x553374;try{console['log'](_0x3d4a(0x31),_0x44404a);const _0x45644f=await getFileSizeFromUri(_0x44404a),_0x2d6fd3=Math[_0x3d4a(0x4)](_0x582195[_0x3d4a(0x32)](_0x45644f,0x400));console['log'](_0x582195[_0x3d4a(0x33)],_0x2d6fd3,'KB');if(_0x582195['SMBMn'](_0x2d6fd3,maxSizeKB)){if(_0x582195[_0x3d4a(0x34)]===_0x582195[_0x3d4a(0x34)]){console['log'](_0x582195[_0x3d4a(0x35)]);const _0x502b0c=await _0x582195[_0x3d4a(0x36)](imageToBase64,_0x44404a);if(_0x502b0c){if(_0x3d4a(0x37)!==_0x582195[_0x3d4a(0x38)])return{'success':!![],'base64':_0x502b0c,'sizeKB':_0x2d6fd3,'originalSizeKB':_0x2d6fd3,'compressionRatio':0x1};else{const _0x429d41=_0x381130['result'],_0x2b53e7=_0x429d41[_0x3d4a(0x21)](',')[0x1];_0x582195[_0x3d4a(0x39)](_0x3507d9,_0x2b53e7);}}}else _0x582195['LwTuq'](_0x1d846c,_0x4a60bf);}let _0x1f58fc=quality,_0x101cb1=maxWidth,_0x2f262d=maxHeight,_0x5db389=0x0;const _0x19b380=0x8;while(_0x582195[_0x3d4a(0x3a)](_0x5db389,_0x19b380)){_0x5db389++,console[_0x3d4a(0x3b)](_0x3d4a(0x3c)+_0x5db389+_0x3d4a(0x3d)+_0x1f58fc+',\x20size='+_0x101cb1+'x'+_0x2f262d);try{if(_0x582195['IXyGQ'](_0x582195[_0x3d4a(0x3e)],'DNfzg')){const _0x739286=await _0x42342f[_0x3d4a(0x3f)](_0x44404a,_0x101cb1,_0x2f262d,format,Math[_0x3d4a(0x4)](_0x582195[_0x3d4a(0x40)](_0x1f58fc,0x64)),0x0,undefined,![],{'mode':_0x3d4a(0x41),'onlyScaleDown':!![]}),_0x4f2a48=await _0x582195[_0x3d4a(0x42)](getFileSizeFromUri,_0x739286[_0x3d4a(0x43)]),_0x1e95c6=Math['round'](_0x582195[_0x3d4a(0x44)](_0x4f2a48,0x400));console[_0x3d4a(0x3b)](_0x3d4a(0x45)+_0x5db389+'\x20result:\x20'+_0x1e95c6+_0x3d4a(0x46));if(_0x582195[_0x3d4a(0x47)](_0x1e95c6,maxSizeKB)){console['log'](_0x582195[_0x3d4a(0x48)]);const _0x5a1e47=await imageToBase64(_0x739286[_0x3d4a(0x43)]);if(_0x5a1e47){const _0x33f159=_0x582195['Obety'](_0x2d6fd3,_0x1e95c6);return console[_0x3d4a(0x3b)](_0x582195['bciIg'],{'originalSizeKB':_0x2d6fd3,'finalSizeKB':_0x1e95c6,'compressionRatio':_0x582195['nZfBX'](_0x33f159[_0x3d4a(0x49)](0x2),'x'),'attempts':_0x5db389}),{'success':!![],'base64':_0x5a1e47,'sizeKB':_0x1e95c6,'originalSizeKB':_0x2d6fd3,'compressionRatio':_0x33f159};}}if(_0x582195[_0x3d4a(0x4a)](_0x1e95c6,maxSizeKB)){if(_0x582195['qzLHS']===_0x3d4a(0x2a)){const _0x21555d=_0x582195[_0x3d4a(0x32)](_0x1e95c6,maxSizeKB);if(_0x582195[_0x3d4a(0x4b)](_0x21555d,0x2))_0x1f58fc*=0.6,_0x101cb1=Math['round'](_0x582195[_0x3d4a(0x40)](_0x101cb1,0.8)),_0x2f262d=Math[_0x3d4a(0x4)](_0x2f262d*0.8);else _0x582195['izpkp'](_0x21555d,1.5)?(_0x1f58fc*=0.75,_0x101cb1=Math['round'](_0x582195['PGHpW'](_0x101cb1,0.9)),_0x2f262d=Math[_0x3d4a(0x4)](_0x582195[_0x3d4a(0x40)](_0x2f262d,0.9))):_0x582195[_0x3d4a(0x4c)](_0x582195[_0x3d4a(0x4d)],_0x582195[_0x3d4a(0x4e)])?_0x29be7d[_0x3d4a(0xa)](_0x582195[_0x3d4a(0x4f)],_0xcb1d2f):_0x1f58fc*=0.85;_0x1f58fc=Math[_0x3d4a(0x6)](0.1,_0x1f58fc),_0x101cb1=Math[_0x3d4a(0x6)](0x190,_0x101cb1),_0x2f262d=Math[_0x3d4a(0x6)](0x190,_0x2f262d);}else _0x4b3999*=0.6,_0x25c50c=_0x52ada2[_0x3d4a(0x4)](_0x5ea773*0.8),_0x14e6ac=_0x46f846['round'](_0x582195[_0x3d4a(0x40)](_0x46ef5d,0.8));}}else _0x57f61a*=0.85;}catch(_0x330cfa){if(_0x582195['NZtFS'](_0x582195[_0x3d4a(0x50)],_0x582195['JggDe']))_0x12d656*=0.75,_0x411360=_0x563102[_0x3d4a(0x4)](_0x582195[_0x3d4a(0x51)](_0x57bb2e,0.9)),_0x1ed8c7=_0x106dcc[_0x3d4a(0x4)](_0x582195['oPfRd'](_0x57cc37,0.9));else{console['error'](_0x3d4a(0x52)+_0x5db389+'\x20failed:',_0x330cfa),_0x1f58fc*=0.7,_0x101cb1=Math[_0x3d4a(0x4)](_0x101cb1*0.8),_0x2f262d=Math['round'](_0x582195[_0x3d4a(0x51)](_0x2f262d,0.8));if(_0x582195[_0x3d4a(0x3a)](_0x1f58fc,0.1)||_0x582195['RlqdF'](_0x101cb1,0xc8)||_0x582195[_0x3d4a(0x53)](_0x2f262d,0xc8))break;}}}console[_0x3d4a(0x3b)](_0x582195[_0x3d4a(0x54)]);try{const _0x109958=await _0x42342f['createResizedImage'](_0x44404a,Math[_0x3d4a(0x6)](0x190,_0x101cb1),Math[_0x3d4a(0x6)](0x190,_0x2f262d),format,0x1e,0x0,undefined,![],{'mode':_0x582195['HKXiE'],'onlyScaleDown':!![]}),_0xeb8357=await getFileSizeFromUri(_0x109958[_0x3d4a(0x43)]),_0x5c15d8=Math['round'](_0x582195[_0x3d4a(0x44)](_0xeb8357,0x400)),_0x5994f3=await imageToBase64(_0x109958[_0x3d4a(0x43)]);if(_0x5994f3)return console[_0x3d4a(0x3b)]('📤\x20[COMPRESSION]\x20Final\x20result\x20(best\x20effort):',_0x5c15d8,'KB'),{'success':!![],'base64':_0x5994f3,'sizeKB':_0x5c15d8,'originalSizeKB':_0x2d6fd3,'compressionRatio':_0x582195['viRMr'](_0x2d6fd3,_0x5c15d8)};}catch(_0x5c1c74){if(_0x582195['NZtFS'](_0x582195[_0x3d4a(0x55)],'jbmtc')){const _0x17bf53=_0x582195['WqFHG'](_0x2adac6,_0x1dd150);return _0x4b7c4a[_0x3d4a(0x3b)](_0x3d4a(0x29),{'originalSizeKB':_0xcbe195,'finalSizeKB':_0x1bf918,'compressionRatio':_0x582195[_0x3d4a(0x56)](_0x17bf53['toFixed'](0x2),'x'),'attempts':_0x269951}),{'success':!![],'base64':_0x3a9a45,'sizeKB':_0x36d027,'originalSizeKB':_0x135f69,'compressionRatio':_0x17bf53};}else console[_0x3d4a(0xa)](_0x582195[_0x3d4a(0x4f)],_0x5c1c74);}return{'success':![],'error':_0x3d4a(0x57)+maxSizeKB+_0x3d4a(0x58)+_0x19b380+'\x20attempts','originalSizeKB':_0x2d6fd3};}catch(_0x3abc10){return console[_0x3d4a(0xa)](_0x582195[_0x3d4a(0x59)],_0x3abc10),{'success':![],'error':_0x582195[_0x3d4a(0x5a)](_0x3abc10,Error)?_0x3abc10[_0x3d4a(0x22)]:_0x3d4a(0x10),'originalSizeKB':0x0};}};export const compressProfilePicture=async _0x1c20b2=>{const _0x1ab723={'cwSaM':function(_0x4a5d42,_0x400292,_0x307670){return _0x4a5d42(_0x400292,_0x307670);},'QWlqY':_0x3d4a(0xd)};return _0x1ab723[_0x3d4a(0x5b)](compressImageToTarget,_0x1c20b2,{'maxSizeKB':0x12c,'maxWidth':0x4b0,'maxHeight':0x4b0,'quality':0.8,'format':_0x1ab723[_0x3d4a(0x5c)]});};export const compressForUpload=async(_0xea687b,_0x1e1137=0x12c)=>{const _0x208f8e={'vfKvU':function(_0x46caeb,_0x5490b4,_0x2716ef){return _0x46caeb(_0x5490b4,_0x2716ef);}};return _0x208f8e[_0x3d4a(0x5d)](compressImageToTarget,_0xea687b,{'maxSizeKB':_0x1e1137,'maxWidth':0x4b0,'maxHeight':0x4b0,'quality':0.8,'format':_0x3d4a(0xd)});};export const convertImageToOptimizedBase64=async(_0x607b8d,_0x5e3f34=0.8)=>{const _0x12e95f={'BtpeI':function(_0x27f247,_0x2aa655,_0x52bbaa){return _0x27f247(_0x2aa655,_0x52bbaa);},'tqbAG':'JPEG'},_0x2276c6=await _0x12e95f['BtpeI'](compressImageToTarget,_0x607b8d,{'maxSizeKB':0x12c,'quality':_0x5e3f34,'format':_0x12e95f[_0x3d4a(0x5e)]});return _0x2276c6[_0x3d4a(0x5f)]?_0x2276c6['base64']||null:null;};function _0x4ca2(){const _0x179da9=['oxQts','Error\x20getting\x20file\x20size:','kYews','zbbmO','round','MmnhA','max','blob','size','aaYZt','error','aWLVs','xTxey','JPEG','HFKHI','❌\x20[COMPRESSION]\x20Compression\x20service\x20error:','Unknown\x20compression\x20error','iHPTW','WVZjj','Error\x20converting\x20image\x20to\x20base64:','JZShQ','WexEr','RBwZV','wcshz','ZyEvt','result','JGVCw','GoIIe','bIJer','HkHrp','QFJgK','onerror','readAsDataURL','split','message','gWaNZ','qwgEa','❌\x20[COMPRESSION]\x20Final\x20compression\x20attempt\x20failed:','📊\x20[COMPRESSION]\x20Original\x20size:','VNOAh','✅\x20[COMPRESSION]\x20Image\x20already\x20under\x20target\x20size','🎯\x20[COMPRESSION]\x20Success:','ujoOg','oPCPX','VLnXP','ohaPK','⚠️\x20[COMPRESSION]\x20Max\x20attempts\x20reached,\x20using\x20best\x20effort','jbmtc','oHObZ','🖼️\x20[COMPRESSION]\x20Starting\x20compression\x20for:','uMwFv','KmSib','BqgAx','fKRjr','EFESd','ylZTk','cMIYU','LwTuq','RlqdF','log','🔄\x20[COMPRESSION]\x20Attempt\x20',':\x20quality=','UxTEX','createResizedImage','dQjDs','contain','Oqqtk','uri','IfNwT','📊\x20[COMPRESSION]\x20Attempt\x20','\x20KB','EOlSw','WUkkf','toFixed','HyyKR','OXKzb','VFVpk','jEfOm','zZRPK','IffPN','JggDe','oPfRd','❌\x20[COMPRESSION]\x20Resize\x20attempt\x20','AxmNg','dCtVC','NIhdx','nZfBX','Failed\x20to\x20compress\x20image\x20to\x20','KB\x20after\x20','KTxms','rqcIt','cwSaM','QWlqY','vfKvU','tqbAG','success'];_0x4ca2=function(){return _0x179da9;};return _0x4ca2();}
|
|
1
|
+
import ImageResizer from '@bam.tech/react-native-image-resizer';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Comprehensive image compression service for React Native
|
|
5
|
+
* Supports iterative compression to meet specific size targets
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Get file size from URI (React Native compatible)
|
|
10
|
+
*/
|
|
11
|
+
const getFileSizeFromUri = async uri => {
|
|
12
|
+
try {
|
|
13
|
+
const response = await fetch(uri);
|
|
14
|
+
const blob = await response.blob();
|
|
15
|
+
return blob.size;
|
|
16
|
+
} catch (error) {
|
|
17
|
+
console.error('Error getting file size:', error);
|
|
18
|
+
return 0;
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Convert image to base64 string
|
|
24
|
+
*/
|
|
25
|
+
const imageToBase64 = async uri => {
|
|
26
|
+
try {
|
|
27
|
+
const response = await fetch(uri);
|
|
28
|
+
const blob = await response.blob();
|
|
29
|
+
return new Promise((resolve, reject) => {
|
|
30
|
+
const reader = new FileReader();
|
|
31
|
+
reader.onloadend = () => {
|
|
32
|
+
try {
|
|
33
|
+
const base64data = reader.result;
|
|
34
|
+
// Remove the data:image/jpeg;base64, prefix
|
|
35
|
+
const base64 = base64data.split(',')[1];
|
|
36
|
+
resolve(base64);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
reject(error);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
reader.onerror = reject;
|
|
42
|
+
reader.readAsDataURL(blob);
|
|
43
|
+
});
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.error('Error converting image to base64:', error);
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Compress image with iterative quality reduction to meet size target
|
|
52
|
+
*/
|
|
53
|
+
export const compressImageToTarget = async (imageUri, options = {}) => {
|
|
54
|
+
const {
|
|
55
|
+
maxSizeKB = 300,
|
|
56
|
+
maxWidth = 1200,
|
|
57
|
+
maxHeight = 1200,
|
|
58
|
+
quality = 0.8,
|
|
59
|
+
format = 'JPEG'
|
|
60
|
+
} = options;
|
|
61
|
+
try {
|
|
62
|
+
console.log('🖼️ [COMPRESSION] Starting compression for:', imageUri);
|
|
63
|
+
|
|
64
|
+
// Get original file size
|
|
65
|
+
const originalSize = await getFileSizeFromUri(imageUri);
|
|
66
|
+
const originalSizeKB = Math.round(originalSize / 1024);
|
|
67
|
+
console.log('📊 [COMPRESSION] Original size:', originalSizeKB, 'KB');
|
|
68
|
+
|
|
69
|
+
// If already under target, just convert to base64
|
|
70
|
+
if (originalSizeKB <= maxSizeKB) {
|
|
71
|
+
console.log('✅ [COMPRESSION] Image already under target size');
|
|
72
|
+
const base64 = await imageToBase64(imageUri);
|
|
73
|
+
if (base64) {
|
|
74
|
+
return {
|
|
75
|
+
success: true,
|
|
76
|
+
base64,
|
|
77
|
+
sizeKB: originalSizeKB,
|
|
78
|
+
originalSizeKB,
|
|
79
|
+
compressionRatio: 1.0
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Start with initial compression parameters
|
|
85
|
+
let currentQuality = quality;
|
|
86
|
+
let currentWidth = maxWidth;
|
|
87
|
+
let currentHeight = maxHeight;
|
|
88
|
+
let attempts = 0;
|
|
89
|
+
const maxAttempts = 8;
|
|
90
|
+
while (attempts < maxAttempts) {
|
|
91
|
+
attempts++;
|
|
92
|
+
console.log(`🔄 [COMPRESSION] Attempt ${attempts}: quality=${currentQuality}, size=${currentWidth}x${currentHeight}`);
|
|
93
|
+
try {
|
|
94
|
+
// Resize and compress the image
|
|
95
|
+
const resizedImage = await ImageResizer.createResizedImage(imageUri, currentWidth, currentHeight, format, Math.round(currentQuality * 100),
|
|
96
|
+
// Convert to percentage
|
|
97
|
+
0,
|
|
98
|
+
// rotation
|
|
99
|
+
undefined,
|
|
100
|
+
// outputPath
|
|
101
|
+
false,
|
|
102
|
+
// keepMeta
|
|
103
|
+
{
|
|
104
|
+
mode: 'contain',
|
|
105
|
+
// Maintain aspect ratio
|
|
106
|
+
onlyScaleDown: true // Don't upscale
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
// Check the size of the compressed image
|
|
110
|
+
const compressedSize = await getFileSizeFromUri(resizedImage.uri);
|
|
111
|
+
const compressedSizeKB = Math.round(compressedSize / 1024);
|
|
112
|
+
console.log(`📊 [COMPRESSION] Attempt ${attempts} result: ${compressedSizeKB} KB`);
|
|
113
|
+
|
|
114
|
+
// If we've hit our target, convert to base64 and return
|
|
115
|
+
if (compressedSizeKB <= maxSizeKB) {
|
|
116
|
+
console.log('✅ [COMPRESSION] Target size achieved!');
|
|
117
|
+
const base64 = await imageToBase64(resizedImage.uri);
|
|
118
|
+
if (base64) {
|
|
119
|
+
const compressionRatio = originalSizeKB / compressedSizeKB;
|
|
120
|
+
console.log('🎯 [COMPRESSION] Success:', {
|
|
121
|
+
originalSizeKB,
|
|
122
|
+
finalSizeKB: compressedSizeKB,
|
|
123
|
+
compressionRatio: compressionRatio.toFixed(2) + 'x',
|
|
124
|
+
attempts
|
|
125
|
+
});
|
|
126
|
+
return {
|
|
127
|
+
success: true,
|
|
128
|
+
base64,
|
|
129
|
+
sizeKB: compressedSizeKB,
|
|
130
|
+
originalSizeKB,
|
|
131
|
+
compressionRatio
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// If still too large, adjust parameters for next attempt
|
|
137
|
+
if (compressedSizeKB > maxSizeKB) {
|
|
138
|
+
// Reduce quality more aggressively if we're way over
|
|
139
|
+
const sizeRatio = compressedSizeKB / maxSizeKB;
|
|
140
|
+
if (sizeRatio > 2.0) {
|
|
141
|
+
// Way too big - reduce quality and dimensions significantly
|
|
142
|
+
currentQuality *= 0.6;
|
|
143
|
+
currentWidth = Math.round(currentWidth * 0.8);
|
|
144
|
+
currentHeight = Math.round(currentHeight * 0.8);
|
|
145
|
+
} else if (sizeRatio > 1.5) {
|
|
146
|
+
// Moderately too big - reduce quality more
|
|
147
|
+
currentQuality *= 0.75;
|
|
148
|
+
currentWidth = Math.round(currentWidth * 0.9);
|
|
149
|
+
currentHeight = Math.round(currentHeight * 0.9);
|
|
150
|
+
} else {
|
|
151
|
+
// Close to target - fine-tune quality
|
|
152
|
+
currentQuality *= 0.85;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Ensure we don't go below minimum thresholds
|
|
156
|
+
currentQuality = Math.max(0.1, currentQuality);
|
|
157
|
+
currentWidth = Math.max(400, currentWidth);
|
|
158
|
+
currentHeight = Math.max(400, currentHeight);
|
|
159
|
+
}
|
|
160
|
+
} catch (resizeError) {
|
|
161
|
+
console.error(`❌ [COMPRESSION] Resize attempt ${attempts} failed:`, resizeError);
|
|
162
|
+
|
|
163
|
+
// Try with more aggressive settings
|
|
164
|
+
currentQuality *= 0.7;
|
|
165
|
+
currentWidth = Math.round(currentWidth * 0.8);
|
|
166
|
+
currentHeight = Math.round(currentHeight * 0.8);
|
|
167
|
+
if (currentQuality < 0.1 || currentWidth < 200 || currentHeight < 200) {
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// If we've exhausted all attempts, return the best effort
|
|
174
|
+
console.log('⚠️ [COMPRESSION] Max attempts reached, using best effort');
|
|
175
|
+
try {
|
|
176
|
+
const finalImage = await ImageResizer.createResizedImage(imageUri, Math.max(400, currentWidth), Math.max(400, currentHeight), format, 30,
|
|
177
|
+
// Very low quality as last resort
|
|
178
|
+
0, undefined, false, {
|
|
179
|
+
mode: 'contain',
|
|
180
|
+
onlyScaleDown: true
|
|
181
|
+
});
|
|
182
|
+
const finalSize = await getFileSizeFromUri(finalImage.uri);
|
|
183
|
+
const finalSizeKB = Math.round(finalSize / 1024);
|
|
184
|
+
const base64 = await imageToBase64(finalImage.uri);
|
|
185
|
+
if (base64) {
|
|
186
|
+
console.log('📤 [COMPRESSION] Final result (best effort):', finalSizeKB, 'KB');
|
|
187
|
+
return {
|
|
188
|
+
success: true,
|
|
189
|
+
base64,
|
|
190
|
+
sizeKB: finalSizeKB,
|
|
191
|
+
originalSizeKB,
|
|
192
|
+
compressionRatio: originalSizeKB / finalSizeKB
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
} catch (finalError) {
|
|
196
|
+
console.error('❌ [COMPRESSION] Final compression attempt failed:', finalError);
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
success: false,
|
|
200
|
+
error: `Failed to compress image to ${maxSizeKB}KB after ${maxAttempts} attempts`,
|
|
201
|
+
originalSizeKB
|
|
202
|
+
};
|
|
203
|
+
} catch (error) {
|
|
204
|
+
console.error('❌ [COMPRESSION] Compression service error:', error);
|
|
205
|
+
return {
|
|
206
|
+
success: false,
|
|
207
|
+
error: error instanceof Error ? error.message : 'Unknown compression error',
|
|
208
|
+
originalSizeKB: 0
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Quick compression for profile pictures (300KB target)
|
|
215
|
+
*/
|
|
216
|
+
export const compressProfilePicture = async imageUri => {
|
|
217
|
+
return compressImageToTarget(imageUri, {
|
|
218
|
+
maxSizeKB: 300,
|
|
219
|
+
maxWidth: 1200,
|
|
220
|
+
maxHeight: 1200,
|
|
221
|
+
quality: 0.8,
|
|
222
|
+
format: 'JPEG'
|
|
223
|
+
});
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Compress image for upload with custom settings
|
|
228
|
+
*/
|
|
229
|
+
export const compressForUpload = async (imageUri, maxSizeKB = 300) => {
|
|
230
|
+
return compressImageToTarget(imageUri, {
|
|
231
|
+
maxSizeKB,
|
|
232
|
+
maxWidth: 1200,
|
|
233
|
+
maxHeight: 1200,
|
|
234
|
+
quality: 0.8,
|
|
235
|
+
format: 'JPEG'
|
|
236
|
+
});
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Legacy function for backward compatibility
|
|
241
|
+
*/
|
|
242
|
+
export const convertImageToOptimizedBase64 = async (imageUri, quality = 0.8) => {
|
|
243
|
+
const result = await compressImageToTarget(imageUri, {
|
|
244
|
+
maxSizeKB: 300,
|
|
245
|
+
quality,
|
|
246
|
+
format: 'JPEG'
|
|
247
|
+
});
|
|
248
|
+
return result.success ? result.base64 || null : null;
|
|
249
|
+
};
|
|
250
|
+
//# sourceMappingURL=imageCompressionService.js.map
|