@onairos/react-native 3.0.39 → 3.0.42
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/components/TrainingModal.js +195 -19
- package/lib/commonjs/components/TrainingModal.js.map +1 -1
- package/lib/commonjs/components/UniversalOnboarding.js +21 -9
- package/lib/commonjs/components/UniversalOnboarding.js.map +1 -1
- package/lib/commonjs/components/onboarding/OAuthWebView.js +56 -5
- package/lib/commonjs/components/onboarding/OAuthWebView.js.map +1 -1
- package/lib/commonjs/services/platformAuthService.js +64 -1
- package/lib/commonjs/services/platformAuthService.js.map +1 -1
- package/lib/module/components/TrainingModal.js +195 -20
- package/lib/module/components/TrainingModal.js.map +1 -1
- package/lib/module/components/UniversalOnboarding.js +23 -11
- package/lib/module/components/UniversalOnboarding.js.map +1 -1
- package/lib/module/components/onboarding/OAuthWebView.js +56 -5
- package/lib/module/components/onboarding/OAuthWebView.js.map +1 -1
- package/lib/module/services/platformAuthService.js +62 -0
- package/lib/module/services/platformAuthService.js.map +1 -1
- package/lib/typescript/components/TrainingModal.d.ts.map +1 -1
- package/lib/typescript/components/UniversalOnboarding.d.ts.map +1 -1
- package/lib/typescript/components/onboarding/OAuthWebView.d.ts.map +1 -1
- package/lib/typescript/services/platformAuthService.d.ts +7 -0
- package/lib/typescript/services/platformAuthService.d.ts.map +1 -1
- package/package.json +4 -2
- package/src/components/TrainingModal.tsx +200 -14
- package/src/components/UniversalOnboarding.tsx +25 -10
- package/src/components/onboarding/OAuthWebView.tsx +51 -5
- package/src/services/platformAuthService.ts +64 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
View,
|
|
4
4
|
Text,
|
|
@@ -10,8 +10,10 @@ import {
|
|
|
10
10
|
Animated,
|
|
11
11
|
TouchableWithoutFeedback,
|
|
12
12
|
SafeAreaView,
|
|
13
|
+
Image,
|
|
13
14
|
} from 'react-native';
|
|
14
15
|
import Icon from 'react-native-vector-icons/MaterialIcons';
|
|
16
|
+
import { io, Socket } from 'socket.io-client';
|
|
15
17
|
import { COLORS } from '../constants';
|
|
16
18
|
import type { TrainingModalProps } from '../types';
|
|
17
19
|
|
|
@@ -26,7 +28,170 @@ export const TrainingModal: React.FC<TrainingModalProps> = ({
|
|
|
26
28
|
modelKey,
|
|
27
29
|
username,
|
|
28
30
|
}) => {
|
|
29
|
-
|
|
31
|
+
// Socket and training state
|
|
32
|
+
const socketRef = useRef<Socket | null>(null);
|
|
33
|
+
const [socketConnected, setSocketConnected] = useState(false);
|
|
34
|
+
const [trainingStatus, setTrainingStatus] = useState('Initializing...');
|
|
35
|
+
const [hasError, setHasError] = useState(false);
|
|
36
|
+
const [isTrainingComplete, setIsTrainingComplete] = useState(false);
|
|
37
|
+
const [userTraits, setUserTraits] = useState<any>(null);
|
|
38
|
+
const [inferenceResults, setInferenceResults] = useState<any>(null);
|
|
39
|
+
const [internalProgress, setInternalProgress] = useState(0);
|
|
40
|
+
|
|
41
|
+
// Use internal progress if available, otherwise fall back to prop progress
|
|
42
|
+
const currentProgress = internalProgress > 0 ? internalProgress / 100 : progress;
|
|
43
|
+
const progressPercentage = Math.round(currentProgress * 100);
|
|
44
|
+
|
|
45
|
+
// Mock user data for now - in real implementation this would come from props
|
|
46
|
+
const userToken = 'mock-token'; // TODO: Get from actual auth
|
|
47
|
+
const userInfo = {
|
|
48
|
+
username: username || 'mobile_user',
|
|
49
|
+
email: null,
|
|
50
|
+
id: null,
|
|
51
|
+
name: username || 'mobile_user'
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// Start Enoch training via API
|
|
55
|
+
const startEnochTraining = async (socketId: string) => {
|
|
56
|
+
try {
|
|
57
|
+
setTrainingStatus('Starting training...');
|
|
58
|
+
setInternalProgress(10);
|
|
59
|
+
|
|
60
|
+
if (!userToken) {
|
|
61
|
+
throw new Error('No authentication token available');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
console.log('🚀 Starting Enoch training with socketId:', socketId);
|
|
65
|
+
|
|
66
|
+
// Prepare user data for training
|
|
67
|
+
const trainingData = {
|
|
68
|
+
socketId,
|
|
69
|
+
username: userInfo?.username || userInfo?.name || username || 'mobile_user',
|
|
70
|
+
email: userInfo?.email || null,
|
|
71
|
+
modelKey: modelKey || null,
|
|
72
|
+
userId: userInfo?.id || null
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
console.log('📤 Sending training data:', trainingData);
|
|
76
|
+
|
|
77
|
+
// For now, simulate the API call since we don't have real tokens
|
|
78
|
+
// TODO: Uncomment when real authentication is available
|
|
79
|
+
/*
|
|
80
|
+
const response = await fetch('https://api2.onairos.uk/enoch/trainModel/mobile', {
|
|
81
|
+
method: 'POST',
|
|
82
|
+
headers: {
|
|
83
|
+
'Content-Type': 'application/json',
|
|
84
|
+
'Authorization': `Bearer ${userToken}`
|
|
85
|
+
},
|
|
86
|
+
body: JSON.stringify(trainingData)
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const result = await response.json();
|
|
90
|
+
|
|
91
|
+
if (result.success) {
|
|
92
|
+
console.log('🚀 Training Started:', result.message);
|
|
93
|
+
setTrainingStatus('Training model...');
|
|
94
|
+
setInternalProgress(20);
|
|
95
|
+
} else {
|
|
96
|
+
console.error('Training start failed:', result.error);
|
|
97
|
+
setTrainingStatus(`Error: ${result.error}`);
|
|
98
|
+
setHasError(true);
|
|
99
|
+
}
|
|
100
|
+
*/
|
|
101
|
+
|
|
102
|
+
// Simulate successful training start
|
|
103
|
+
console.log('🚀 Training Started (simulated)');
|
|
104
|
+
setTrainingStatus('Training model...');
|
|
105
|
+
setInternalProgress(20);
|
|
106
|
+
|
|
107
|
+
} catch (error) {
|
|
108
|
+
console.error('Training start error:', error);
|
|
109
|
+
setTrainingStatus(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
110
|
+
setHasError(true);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// Setup socket connection and training
|
|
115
|
+
useEffect(() => {
|
|
116
|
+
if (!visible || !userInfo) return;
|
|
117
|
+
|
|
118
|
+
console.log('Setting up socket connection for training...');
|
|
119
|
+
console.log('🧑💻 User info available:', userInfo);
|
|
120
|
+
|
|
121
|
+
// For now, simulate the socket connection since we don't have real auth
|
|
122
|
+
// TODO: Uncomment when real authentication is available
|
|
123
|
+
/*
|
|
124
|
+
// Initialize socket connection
|
|
125
|
+
socketRef.current = io('https://api2.onairos.uk', {
|
|
126
|
+
transports: ['websocket'],
|
|
127
|
+
autoConnect: false
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
// Socket event listeners
|
|
131
|
+
socketRef.current.on('connect', () => {
|
|
132
|
+
console.log('✅ Socket connected for training');
|
|
133
|
+
setSocketConnected(true);
|
|
134
|
+
const socketId = socketRef.current?.id;
|
|
135
|
+
if (socketId) {
|
|
136
|
+
startEnochTraining(socketId);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
socketRef.current.on('disconnect', () => {
|
|
141
|
+
console.log('❌ Socket disconnected');
|
|
142
|
+
setSocketConnected(false);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
socketRef.current.on('trainingCompleted', (data) => {
|
|
146
|
+
console.log('✅ Training Complete:', data);
|
|
147
|
+
setTrainingStatus('Running test inference...');
|
|
148
|
+
setInternalProgress(60);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
socketRef.current.on('inferenceCompleted', (data) => {
|
|
152
|
+
console.log('🧠 Inference Complete:', data);
|
|
153
|
+
setTrainingStatus('Uploading to S3...');
|
|
154
|
+
setInternalProgress(80);
|
|
155
|
+
setUserTraits(data.traits);
|
|
156
|
+
setInferenceResults(data.inferenceResults);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
socketRef.current.on('modelStandby', (data) => {
|
|
160
|
+
console.log('🎉 All Complete:', data);
|
|
161
|
+
setIsTrainingComplete(true);
|
|
162
|
+
setTrainingStatus('Complete!');
|
|
163
|
+
setInternalProgress(100);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
socketRef.current.on('trainingUpdate', (data) => {
|
|
167
|
+
if (data.error) {
|
|
168
|
+
console.error('Training update error:', data.error);
|
|
169
|
+
setTrainingStatus(`Error: ${data.error}`);
|
|
170
|
+
setHasError(true);
|
|
171
|
+
} else if (data.progress) {
|
|
172
|
+
setInternalProgress(data.progress);
|
|
173
|
+
setTrainingStatus(data.status || 'Training in progress...');
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
// Connect to socket
|
|
178
|
+
socketRef.current.connect();
|
|
179
|
+
*/
|
|
180
|
+
|
|
181
|
+
// Simulate socket connection and training for now
|
|
182
|
+
console.log('🔌 Simulating socket connection...');
|
|
183
|
+
setSocketConnected(true);
|
|
184
|
+
startEnochTraining('simulated-socket-id');
|
|
185
|
+
|
|
186
|
+
// Cleanup function
|
|
187
|
+
return () => {
|
|
188
|
+
if (socketRef.current) {
|
|
189
|
+
console.log('🔌 Disconnecting training socket...');
|
|
190
|
+
socketRef.current.disconnect();
|
|
191
|
+
socketRef.current = null;
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
}, [visible, userInfo]);
|
|
30
195
|
|
|
31
196
|
return (
|
|
32
197
|
<Modal
|
|
@@ -46,14 +211,20 @@ export const TrainingModal: React.FC<TrainingModalProps> = ({
|
|
|
46
211
|
|
|
47
212
|
<SafeAreaView style={styles.container}>
|
|
48
213
|
<View style={styles.content}>
|
|
49
|
-
<
|
|
50
|
-
|
|
51
|
-
|
|
214
|
+
<Image
|
|
215
|
+
source={require('../assets/images/onairos_logo.png')}
|
|
216
|
+
style={styles.onairosLogo}
|
|
217
|
+
resizeMode="contain"
|
|
218
|
+
/>
|
|
52
219
|
|
|
53
220
|
<Text style={styles.title}>Training Your AI</Text>
|
|
54
221
|
<Text style={styles.subtitle}>
|
|
55
222
|
Creating your personalized model
|
|
56
223
|
</Text>
|
|
224
|
+
|
|
225
|
+
<Text style={styles.statusText}>
|
|
226
|
+
{trainingStatus}
|
|
227
|
+
</Text>
|
|
57
228
|
|
|
58
229
|
<View style={styles.progressContainer}>
|
|
59
230
|
<View style={styles.progressBar}>
|
|
@@ -71,8 +242,17 @@ export const TrainingModal: React.FC<TrainingModalProps> = ({
|
|
|
71
242
|
|
|
72
243
|
<View style={styles.loadingContainer}>
|
|
73
244
|
<ActivityIndicator size="small" color={COLORS.primary} />
|
|
74
|
-
<Text style={styles.loadingText}>
|
|
245
|
+
<Text style={styles.loadingText}>
|
|
246
|
+
{socketConnected ? 'Processing your data...' : 'Connecting to training server...'}
|
|
247
|
+
</Text>
|
|
75
248
|
</View>
|
|
249
|
+
|
|
250
|
+
{hasError && (
|
|
251
|
+
<View style={styles.errorContainer}>
|
|
252
|
+
<Icon name="error-outline" size={24} color="#FF6B6B" />
|
|
253
|
+
<Text style={styles.errorText}>Training encountered an error</Text>
|
|
254
|
+
</View>
|
|
255
|
+
)}
|
|
76
256
|
|
|
77
257
|
<View style={styles.footer}>
|
|
78
258
|
<TouchableOpacity
|
|
@@ -82,7 +262,7 @@ export const TrainingModal: React.FC<TrainingModalProps> = ({
|
|
|
82
262
|
<Text style={styles.cancelButtonText}>Cancel</Text>
|
|
83
263
|
</TouchableOpacity>
|
|
84
264
|
|
|
85
|
-
{
|
|
265
|
+
{(currentProgress >= 1 || isTrainingComplete) && (
|
|
86
266
|
<TouchableOpacity
|
|
87
267
|
style={styles.completeButton}
|
|
88
268
|
onPress={onComplete}
|
|
@@ -153,6 +333,11 @@ const styles = StyleSheet.create({
|
|
|
153
333
|
textAlign: 'center',
|
|
154
334
|
marginBottom: 32,
|
|
155
335
|
},
|
|
336
|
+
statusText: {
|
|
337
|
+
fontSize: 14,
|
|
338
|
+
color: COLORS.text.secondary,
|
|
339
|
+
marginBottom: 24,
|
|
340
|
+
},
|
|
156
341
|
progressContainer: {
|
|
157
342
|
width: '100%',
|
|
158
343
|
marginBottom: 16,
|
|
@@ -224,14 +409,15 @@ const styles = StyleSheet.create({
|
|
|
224
409
|
onairosLogo: {
|
|
225
410
|
width: 48,
|
|
226
411
|
height: 48,
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
412
|
+
},
|
|
413
|
+
errorContainer: {
|
|
414
|
+
flexDirection: 'row',
|
|
230
415
|
alignItems: 'center',
|
|
416
|
+
marginBottom: 24,
|
|
231
417
|
},
|
|
232
|
-
|
|
233
|
-
fontSize:
|
|
234
|
-
|
|
235
|
-
|
|
418
|
+
errorText: {
|
|
419
|
+
fontSize: 14,
|
|
420
|
+
color: '#FF6B6B',
|
|
421
|
+
marginLeft: 8,
|
|
236
422
|
},
|
|
237
423
|
});
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
Image,
|
|
16
16
|
Switch,
|
|
17
17
|
Linking,
|
|
18
|
+
Alert,
|
|
18
19
|
} from 'react-native';
|
|
19
20
|
import Icon from 'react-native-vector-icons/MaterialIcons';
|
|
20
21
|
import { PlatformList } from './PlatformList';
|
|
@@ -23,7 +24,7 @@ import { TrainingModal } from './TrainingModal';
|
|
|
23
24
|
import { OAuthWebView } from './onboarding/OAuthWebView';
|
|
24
25
|
import { useConnections } from '../hooks/useConnections';
|
|
25
26
|
import { COLORS, DEEP_LINK_CONFIG } from '../constants';
|
|
26
|
-
import { initiateOAuth, initiateNativeAuth, hasNativeSDK, isOAuthCallback } from '../services/platformAuthService';
|
|
27
|
+
import { initiateOAuth, initiateNativeAuth, hasNativeSDK, isOAuthCallback, testApiConnectivity } from '../services/platformAuthService';
|
|
27
28
|
import type { UniversalOnboardingProps, ConnectionStatus } from '../types';
|
|
28
29
|
|
|
29
30
|
const { height, width } = Dimensions.get('window');
|
|
@@ -161,15 +162,27 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
161
162
|
// Attempt to connect platform
|
|
162
163
|
try {
|
|
163
164
|
setIsConnectingPlatform(true);
|
|
164
|
-
console.log(
|
|
165
|
+
console.log(`🔌 Initiating connection for ${platformId}`);
|
|
166
|
+
|
|
167
|
+
// Test API connectivity first
|
|
168
|
+
console.log('🔍 Testing API connectivity...');
|
|
169
|
+
const connectivityTest = await testApiConnectivity();
|
|
170
|
+
|
|
171
|
+
if (!connectivityTest.success) {
|
|
172
|
+
console.error('❌ API connectivity test failed:', connectivityTest.error);
|
|
173
|
+
Alert.alert('Network Error', `${connectivityTest.error}\n\nPlease check your internet connection and try again.`);
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
console.log('✅ API connectivity confirmed');
|
|
165
178
|
|
|
166
179
|
// Check if platform has a native SDK
|
|
167
180
|
if (hasNativeSDK(platformId)) {
|
|
168
|
-
console.log(
|
|
181
|
+
console.log(`📱 Using native SDK for ${platformId}`);
|
|
169
182
|
// Use native SDK for authentication
|
|
170
183
|
const success = await initiateNativeAuth(platformId);
|
|
171
184
|
if (success) {
|
|
172
|
-
console.log(
|
|
185
|
+
console.log(`✅ Native authentication successful for ${platformId}`);
|
|
173
186
|
// Update platform toggle state
|
|
174
187
|
setPlatformToggles(prev => ({
|
|
175
188
|
...prev,
|
|
@@ -183,26 +196,28 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
183
196
|
}));
|
|
184
197
|
}
|
|
185
198
|
} else {
|
|
186
|
-
console.log(
|
|
199
|
+
console.log(`🌐 Initiating OAuth flow for ${platformId}`);
|
|
187
200
|
// Use OAuth flow through proxy server
|
|
188
201
|
const oauthUrl = await initiateOAuth(platformId, username, AppName);
|
|
189
202
|
if (oauthUrl) {
|
|
190
|
-
console.log(
|
|
203
|
+
console.log(`✅ Received OAuth URL for ${platformId}:`, oauthUrl);
|
|
191
204
|
setCurrentPlatform(platformId);
|
|
192
205
|
setOauthUrl(oauthUrl);
|
|
193
206
|
setStep('oauth');
|
|
194
207
|
} else {
|
|
195
|
-
console.error(
|
|
208
|
+
console.error(`❌ No OAuth URL returned for ${platformId}`);
|
|
209
|
+
Alert.alert('Error', 'Failed to get authorization URL for this platform. Please try again.');
|
|
196
210
|
}
|
|
197
211
|
}
|
|
198
212
|
} catch (error) {
|
|
199
|
-
console.error(
|
|
213
|
+
console.error(`❌ Error connecting ${platformId}:`, error);
|
|
214
|
+
Alert.alert('Connection Error', `Failed to connect to ${platformId}: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
200
215
|
} finally {
|
|
201
216
|
setIsConnectingPlatform(false);
|
|
202
217
|
}
|
|
203
218
|
} else {
|
|
204
219
|
// Disconnect platform
|
|
205
|
-
console.log(
|
|
220
|
+
console.log(`🔌 Disconnecting ${platformId}`);
|
|
206
221
|
setPlatformToggles(prev => ({
|
|
207
222
|
...prev,
|
|
208
223
|
[platformId]: false
|
|
@@ -215,7 +230,7 @@ export const UniversalOnboarding: React.FC<UniversalOnboardingProps> = ({
|
|
|
215
230
|
return newConnections;
|
|
216
231
|
});
|
|
217
232
|
}
|
|
218
|
-
}, [platformToggles, username]);
|
|
233
|
+
}, [platformToggles, username, AppName]);
|
|
219
234
|
|
|
220
235
|
/**
|
|
221
236
|
* Handles OAuth callback URLs
|
|
@@ -36,7 +36,13 @@ export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
|
|
|
36
36
|
const webViewRef = useRef<WebView>(null);
|
|
37
37
|
const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
38
38
|
|
|
39
|
-
console.log('Opening OAuth WebView with URL:', url);
|
|
39
|
+
console.log('🌐 Opening OAuth WebView with URL:', url);
|
|
40
|
+
console.log('🔗 Platform:', platform);
|
|
41
|
+
console.log('📱 URL Components:', {
|
|
42
|
+
protocol: url.split('://')[0],
|
|
43
|
+
domain: url.split('://')[1]?.split('/')[0],
|
|
44
|
+
path: url.split('://')[1]?.split('/').slice(1).join('/'),
|
|
45
|
+
});
|
|
40
46
|
|
|
41
47
|
// Set up timeout for OAuth flow
|
|
42
48
|
React.useEffect(() => {
|
|
@@ -157,10 +163,50 @@ export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
|
|
|
157
163
|
|
|
158
164
|
const handleError = (syntheticEvent: any) => {
|
|
159
165
|
const { nativeEvent } = syntheticEvent;
|
|
160
|
-
console.error('WebView error:',
|
|
166
|
+
console.error('🚨 WebView error details:', {
|
|
167
|
+
description: nativeEvent.description,
|
|
168
|
+
code: nativeEvent.code,
|
|
169
|
+
domain: nativeEvent.domain,
|
|
170
|
+
url: nativeEvent.url,
|
|
171
|
+
canGoBack: nativeEvent.canGoBack,
|
|
172
|
+
canGoForward: nativeEvent.canGoForward,
|
|
173
|
+
loading: nativeEvent.loading,
|
|
174
|
+
target: nativeEvent.target,
|
|
175
|
+
title: nativeEvent.title,
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// Check for specific NSURLErrorDomain codes
|
|
179
|
+
let errorMessage = 'Failed to load OAuth page.';
|
|
180
|
+
|
|
181
|
+
if (nativeEvent.domain === 'NSURLErrorDomain') {
|
|
182
|
+
switch (nativeEvent.code) {
|
|
183
|
+
case -1009: // NSURLErrorNotConnectedToInternet
|
|
184
|
+
errorMessage = 'No internet connection. Please check your network and try again.';
|
|
185
|
+
break;
|
|
186
|
+
case -1003: // NSURLErrorCannotFindHost
|
|
187
|
+
errorMessage = 'Cannot reach authentication server. Please check your internet connection.';
|
|
188
|
+
break;
|
|
189
|
+
case -1001: // NSURLErrorTimedOut
|
|
190
|
+
errorMessage = 'Connection timed out. Please try again.';
|
|
191
|
+
break;
|
|
192
|
+
case -1200: // NSURLErrorSecureConnectionFailed
|
|
193
|
+
errorMessage = 'Secure connection failed. Please try again.';
|
|
194
|
+
break;
|
|
195
|
+
case -1022: // NSURLErrorAppTransportSecurityRequiresSecureConnection
|
|
196
|
+
errorMessage = 'App Transport Security error. Connection must be secure.';
|
|
197
|
+
break;
|
|
198
|
+
case -1004: // NSURLErrorCannotConnectToHost
|
|
199
|
+
errorMessage = 'Cannot connect to authentication server. Please try again later.';
|
|
200
|
+
break;
|
|
201
|
+
default:
|
|
202
|
+
errorMessage = `Network error (${nativeEvent.code}): ${nativeEvent.description || 'Please check your connection and try again.'}`;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
console.error('🔴 OAuth WebView Error:', errorMessage);
|
|
161
207
|
|
|
162
208
|
if (retryCount < 2) {
|
|
163
|
-
console.log(
|
|
209
|
+
console.log(`🔄 Retrying OAuth load (attempt ${retryCount + 1}/2)`);
|
|
164
210
|
setRetryCount(prev => prev + 1);
|
|
165
211
|
setIsLoading(true);
|
|
166
212
|
setError(null);
|
|
@@ -170,9 +216,9 @@ export const OAuthWebView: React.FC<OAuthWebViewProps> = ({
|
|
|
170
216
|
if (webViewRef.current) {
|
|
171
217
|
webViewRef.current.reload();
|
|
172
218
|
}
|
|
173
|
-
},
|
|
219
|
+
}, 3000);
|
|
174
220
|
} else {
|
|
175
|
-
setError(
|
|
221
|
+
setError(errorMessage);
|
|
176
222
|
setIsLoading(false);
|
|
177
223
|
}
|
|
178
224
|
};
|
|
@@ -72,17 +72,26 @@ export const getPlatformColor = (platform: string): string => {
|
|
|
72
72
|
*/
|
|
73
73
|
export const initiateOAuth = async (platform: string, username: string, appName?: string): Promise<string | null> => {
|
|
74
74
|
try {
|
|
75
|
+
console.log('🚀 Initiating OAuth for platform:', platform);
|
|
76
|
+
console.log('👤 Username:', username);
|
|
77
|
+
console.log('📱 App name:', appName);
|
|
78
|
+
|
|
75
79
|
// Check if the platform is supported
|
|
76
80
|
if (!PLATFORM_AUTH_CONFIG[platform]) {
|
|
81
|
+
console.error('❌ Unsupported platform:', platform);
|
|
77
82
|
throw new Error(`Unsupported platform: ${platform}`);
|
|
78
83
|
}
|
|
79
84
|
|
|
80
85
|
// Check if platform has a native SDK
|
|
81
86
|
if (PLATFORM_AUTH_CONFIG[platform].hasNativeSDK) {
|
|
87
|
+
console.log('📱 Platform uses native SDK, returning null');
|
|
82
88
|
// Return null to indicate that we should use the native SDK
|
|
83
89
|
return null;
|
|
84
90
|
}
|
|
85
91
|
|
|
92
|
+
console.log('🌐 Platform uses OAuth WebView flow');
|
|
93
|
+
console.log('🔗 Auth endpoint:', PLATFORM_AUTH_CONFIG[platform].authEndpoint);
|
|
94
|
+
|
|
86
95
|
// Handle Instagram with specific API format
|
|
87
96
|
if (platform === 'instagram') {
|
|
88
97
|
const state = 'djksbfds';
|
|
@@ -93,6 +102,8 @@ export const initiateOAuth = async (platform: string, username: string, appName?
|
|
|
93
102
|
},
|
|
94
103
|
};
|
|
95
104
|
|
|
105
|
+
console.log('📤 Sending Instagram OAuth request:', jsonData);
|
|
106
|
+
|
|
96
107
|
const response = await fetch('https://api2.onairos.uk/instagram/authorize', {
|
|
97
108
|
method: 'POST',
|
|
98
109
|
headers: {
|
|
@@ -101,12 +112,24 @@ export const initiateOAuth = async (platform: string, username: string, appName?
|
|
|
101
112
|
body: JSON.stringify(jsonData),
|
|
102
113
|
});
|
|
103
114
|
|
|
115
|
+
console.log('📡 Instagram OAuth response status:', response.status);
|
|
116
|
+
console.log('📡 Instagram OAuth response headers:', response.headers);
|
|
117
|
+
|
|
118
|
+
if (!response.ok) {
|
|
119
|
+
const errorText = await response.text();
|
|
120
|
+
console.error('❌ Instagram OAuth API error:', errorText);
|
|
121
|
+
throw new Error(`Instagram OAuth API error: ${response.status} - ${errorText}`);
|
|
122
|
+
}
|
|
123
|
+
|
|
104
124
|
const responseData = await response.json();
|
|
125
|
+
console.log('📥 Instagram OAuth response data:', responseData);
|
|
105
126
|
|
|
106
127
|
if (responseData.instagramURL) {
|
|
128
|
+
console.log('✅ Instagram OAuth URL received:', responseData.instagramURL);
|
|
107
129
|
return responseData.instagramURL;
|
|
108
130
|
}
|
|
109
131
|
|
|
132
|
+
console.error('❌ No Instagram URL found in response');
|
|
110
133
|
throw new Error('No Instagram URL found in response');
|
|
111
134
|
}
|
|
112
135
|
|
|
@@ -119,6 +142,8 @@ export const initiateOAuth = async (platform: string, username: string, appName?
|
|
|
119
142
|
},
|
|
120
143
|
};
|
|
121
144
|
|
|
145
|
+
console.log(`📤 Sending ${platform} OAuth request:`, jsonData);
|
|
146
|
+
|
|
122
147
|
// Make the request to get the OAuth URL
|
|
123
148
|
const response = await fetch(PLATFORM_AUTH_CONFIG[platform].authEndpoint, {
|
|
124
149
|
method: 'POST',
|
|
@@ -128,8 +153,18 @@ export const initiateOAuth = async (platform: string, username: string, appName?
|
|
|
128
153
|
body: JSON.stringify(jsonData),
|
|
129
154
|
});
|
|
130
155
|
|
|
156
|
+
console.log(`📡 ${platform} OAuth response status:`, response.status);
|
|
157
|
+
console.log(`📡 ${platform} OAuth response headers:`, response.headers);
|
|
158
|
+
|
|
159
|
+
if (!response.ok) {
|
|
160
|
+
const errorText = await response.text();
|
|
161
|
+
console.error(`❌ ${platform} OAuth API error:`, errorText);
|
|
162
|
+
throw new Error(`${platform} OAuth API error: ${response.status} - ${errorText}`);
|
|
163
|
+
}
|
|
164
|
+
|
|
131
165
|
// Parse the response
|
|
132
166
|
const data = await response.json();
|
|
167
|
+
console.log(`📥 ${platform} OAuth response data:`, data);
|
|
133
168
|
|
|
134
169
|
// Check if the response contains the OAuth URL based on platform
|
|
135
170
|
switch (platform) {
|
|
@@ -249,3 +284,32 @@ export const isOAuthCallback = (url: string): boolean => {
|
|
|
249
284
|
// Check if the URL starts with our redirect URI
|
|
250
285
|
return url.startsWith('onairosanime://auth/');
|
|
251
286
|
};
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Test connectivity to the Onairos API server
|
|
290
|
+
*/
|
|
291
|
+
export const testApiConnectivity = async (): Promise<{ success: boolean; error?: string }> => {
|
|
292
|
+
try {
|
|
293
|
+
console.log('🔍 Testing connectivity to Onairos API...');
|
|
294
|
+
|
|
295
|
+
const response = await fetch('https://api2.onairos.uk/health', {
|
|
296
|
+
method: 'GET',
|
|
297
|
+
headers: {
|
|
298
|
+
'Content-Type': 'application/json',
|
|
299
|
+
},
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
console.log('🌐 API connectivity test response:', response.status);
|
|
303
|
+
|
|
304
|
+
if (response.ok) {
|
|
305
|
+
console.log('✅ API server is reachable');
|
|
306
|
+
return { success: true };
|
|
307
|
+
} else {
|
|
308
|
+
console.log('⚠️ API server responded with error:', response.status);
|
|
309
|
+
return { success: false, error: `API server error: ${response.status}` };
|
|
310
|
+
}
|
|
311
|
+
} catch (error) {
|
|
312
|
+
console.error('❌ API connectivity test failed:', error);
|
|
313
|
+
return { success: false, error: error instanceof Error ? error.message : 'Unknown error' };
|
|
314
|
+
}
|
|
315
|
+
};
|