Skip to content

Commit 1c1ddd6

Browse files
Merge branch 'dev'
2 parents 2e6d7b1 + ab88394 commit 1c1ddd6

10 files changed

Lines changed: 528 additions & 402 deletions

File tree

js/interface/dropdown/neuritepanel.js

Lines changed: 102 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,125 @@
1-
// Determine if we are on the test or production origins
2-
const isTest = window.location.origin === 'https://test.neurite.network';
3-
const isProd = window.location.origin === 'https://neurite.network';
1+
window.NeuriteEnv = {
2+
isProd: window.location.origin === 'https://neurite.network',
3+
isTest: window.location.origin === 'https://test.neurite.network',
4+
isElectron: window.startedViaElectron === true,
5+
isLocalhostFrontend: window.location.origin === 'http://localhost:8080',
6+
isLocalFileFrontend: window.location.origin === 'null',
7+
8+
get isElectronWithLocalFrontend() {
9+
return this.isElectron && (this.isLocalhostFrontend || this.isLocalFileFrontend);
10+
},
11+
12+
// Used for request fallback or redirect logic
13+
get baseUrl() {
14+
if (this.isProd) return 'https://neurite.network';
15+
if (this.isTest) return 'https://test.neurite.network';
16+
return null; // Electron-local and dev-hosted must proxy
17+
}
18+
}
19+
20+
function neuriteOriginCheck() {
21+
const { isProd, isTest, isElectron } = window.NeuriteEnv;
422

5-
// Set the base URL or null if not on the test or production origins
6-
const NEURITE_BASE_URL = isTest
7-
? 'https://test.neurite.network'
8-
: isProd
9-
? 'https://neurite.network'
10-
: null;
23+
const isValidEnvironment = isProd || isTest || isElectron;
24+
if (isValidEnvironment) return;
25+
26+
alert('Please access Neurite via neurite.network or the official app.');
27+
throw new Error('Blocked request: invalid origin');
28+
}
1129

1230
class NeuriteBackend {
1331
constructor() {
14-
this.baseUrl = NEURITE_BASE_URL;
32+
this.baseUrl = window.NeuriteEnv.baseUrl;
1533
}
1634

17-
// General method for making API calls
1835
async request(endpoint, options = {}) {
19-
neuriteOriginCheck(); // Check origin before making the request
36+
const isStreaming = options.stream === true;
37+
neuriteOriginCheck();
2038

21-
const url = `${this.baseUrl}/api${endpoint}`;
22-
const defaultOptions = {
23-
credentials: 'include', // Include cookies
39+
const url = this.baseUrl ? `${this.baseUrl}/api${endpoint}` : `/api${endpoint}`;
40+
const requestOptions = {
41+
credentials: 'include',
2442
headers: {
2543
'Content-Type': 'application/json',
2644
...(options.headers || {})
2745
},
2846
...options
2947
};
30-
48+
3149
try {
32-
const response = await fetch(url, defaultOptions);
33-
34-
if (response.status === 401) {
35-
if (options.handleUnauthorized) {
36-
// Let the caller handle the unauthorized error
37-
return response;
38-
} else {
39-
// Use the global unauthorized handler
40-
handleNeuriteUnauthorized();
41-
}
42-
}
43-
44-
// Optionally handle other status codes here
45-
46-
return response;
47-
} catch (error) {
48-
console.error(`API request to ${url} failed:`, error);
49-
throw error;
50+
const response = window.NeuriteEnv.isElectronWithLocalFrontend
51+
? await this.#electronRequest(endpoint, requestOptions, isStreaming)
52+
: await fetch(url, requestOptions);
53+
54+
return this.#handleResponse(response, options.handleUnauthorized);
55+
} catch (err) {
56+
Logger.err(`API request to ${url} failed:`, err);
57+
throw err;
5058
}
5159
}
5260

53-
// Example GET request
5461
async get(endpoint, options = {}) {
5562
return this.request(endpoint, { method: 'GET', ...options });
5663
}
5764

58-
// Example POST request
5965
async post(endpoint, body, options = {}) {
6066
return this.request(endpoint, {
6167
method: 'POST',
6268
body: JSON.stringify(body),
6369
...options
6470
});
6571
}
66-
}
6772

73+
async #handleResponse(response, handleUnauthorized) {
74+
if (response.status === 401) {
75+
if (handleUnauthorized) return response;
76+
return handleNeuriteUnauthorized();
77+
}
6878

69-
// Instantiate and make it globally accessible
70-
window.NeuriteBackend = new NeuriteBackend();
79+
return response;
80+
}
81+
82+
async #electronRequest(endpoint, requestOptions, isStreaming) {
83+
if (isStreaming) {
84+
const id = crypto.randomUUID();
85+
const encoder = new TextEncoder();
86+
87+
const stream = new ReadableStream({
88+
start(controller) {
89+
const onChunk = (event, data) => {
90+
if (data.id !== id) return;
91+
92+
if (data.chunk) controller.enqueue(encoder.encode(data.chunk));
93+
if (data.done) {
94+
controller.close();
95+
window.electronAPI._removeStreamListener(onChunk);
96+
}
97+
if (data.error) {
98+
controller.error(new Error(data.error));
99+
window.electronAPI._removeStreamListener(onChunk);
100+
}
101+
};
102+
window.electronAPI._addStreamListener(onChunk);
103+
}
104+
});
105+
106+
window.electronAPI.sendStreamRequest(id, `/api${endpoint}`, requestOptions);
71107

108+
return new Response(stream, {
109+
headers: { 'Content-Type': 'application/json' }
110+
});
111+
}
112+
113+
const response = await window.electronAPI.secureFetch(endpoint, requestOptions);
114+
return {
115+
ok: response.ok,
116+
status: response.status,
117+
json: async () => response.data
118+
};
119+
}
120+
}
121+
122+
window.NeuriteBackend = new NeuriteBackend();
72123

73124

74125
// neuritePanel.js
@@ -103,29 +154,29 @@ class NeuritePanel {
103154
if (storedEmail && emailDisplay) {
104155
emailDisplay.textContent = storedEmail;
105156
} else if (!emailDisplay) {
106-
console.warn('Email display element not found.');
157+
Logger.warn('Email display element not found.');
107158
}
108159

109160
this.setupTabEventListeners();
110161

111162
if (this.addFundsButton) {
112163
this.addFundsButton.addEventListener('click', () => this.balanceHandler.addFunds());
113164
} else {
114-
console.error('Add funds button not found.');
165+
Logger.err('Add funds button not found.');
115166
}
116167

117168
if (this.signOutButton) {
118169
this.signOutButton.addEventListener('click', signOut);
119170
} else {
120-
console.error('Sign out button not found.');
171+
Logger.err('Sign out button not found.');
121172
}
122173

123174
// Initialize Delete Account Button
124175
this.deleteAccountButton = document.getElementById('delete-account-btn');
125176
if (this.deleteAccountButton) {
126177
this.deleteAccountButton.addEventListener('click', () => this.handleDeleteAccount());
127178
} else {
128-
console.error('Delete Account button not found.');
179+
Logger.err('Delete Account button not found.');
129180
}
130181
}
131182

@@ -148,7 +199,7 @@ class NeuritePanel {
148199
});
149200
});
150201
} else {
151-
console.error(`Label for ${labelId} not found.`);
202+
Logger.err(`Label for ${labelId} not found.`);
152203
}
153204
});
154205
}
@@ -173,11 +224,11 @@ class NeuritePanel {
173224
// Update local storage
174225
localStorage.setItem('userBalance', balance);
175226
} catch (error) {
176-
console.error('Error fetching balance:', error);
227+
Logger.err('Error fetching balance:', error);
177228
if (this.balanceDisplay) {
178229
this.balanceDisplay.textContent = 'error';
179230
} else {
180-
console.warn('Balance display element not found. Cannot display error.');
231+
Logger.warn('Balance display element not found. Cannot display error.');
181232
}
182233
this.updateBalanceBar(0);
183234
return;
@@ -209,7 +260,7 @@ class NeuritePanel {
209260
if (this.balanceDisplay) {
210261
this.balanceDisplay.textContent = `$${safeBalance.toFixed(2)}`;
211262
} else {
212-
//console.warn('Balance display element not found. Skipping balance display update.');
263+
//Logger.warn('Balance display element not found. Skipping balance display update.');
213264
}
214265

215266
// Update balance bar if element exists
@@ -247,7 +298,7 @@ class NeuritePanel {
247298
updateSignInState();
248299
}
249300
} catch (error) {
250-
console.error('Delete Account Error:', error);
301+
Logger.err('Delete Account Error:', error);
251302
alert(`Error deleting account: ${error.message}`);
252303
this.deleteAccountButton.disabled = false;
253304
}
@@ -259,7 +310,7 @@ class NeuritePanel {
259310
if (this.balanceBar) {
260311
this.balanceBar.style.width = `${percentage}%`;
261312
} else {
262-
//console.warn('Balance bar element not found. Skipping balance bar update.');
313+
//Logger.warn('Balance bar element not found. Skipping balance bar update.');
263314
}
264315
}
265316

@@ -352,7 +403,7 @@ class BalanceHandler {
352403
const data = await response.json();
353404
return data.balance;
354405
} catch (error) {
355-
console.error('Error fetching balance:', error);
406+
Logger.err('Error fetching balance:', error);
356407
throw error;
357408
}
358409
}
@@ -370,7 +421,7 @@ class BalanceHandler {
370421
const data = await response.json();
371422
return data.sessionId;
372423
} catch (error) {
373-
console.error('Error creating checkout session:', error);
424+
Logger.err('Error creating checkout session:', error);
374425
throw error;
375426
}
376427
}

0 commit comments

Comments
 (0)