pinokiod 3.51.0 → 3.53.0
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/kernel/gitconfig_template +3 -1
- package/kernel/index.js +65 -43
- package/kernel/peer.js +21 -8
- package/kernel/router/index.js +10 -10
- package/kernel/router/localhost_static_router.js +3 -0
- package/kernel/router/peer_static_router.js +1 -0
- package/kernel/scripts/git/create +1 -2
- package/kernel/scripts/git/push +1 -1
- package/package.json +6 -2
- package/server/index.js +178 -87
- package/server/public/common.js +0 -13
- package/server/public/serve/directory.html +106 -0
- package/server/public/serve/icons/application_xp.png +0 -0
- package/server/public/serve/icons/application_xp_terminal.png +0 -0
- package/server/public/serve/icons/box.png +0 -0
- package/server/public/serve/icons/cd.png +0 -0
- package/server/public/serve/icons/controller.png +0 -0
- package/server/public/serve/icons/drive.png +0 -0
- package/server/public/serve/icons/film.png +0 -0
- package/server/public/serve/icons/folder.png +0 -0
- package/server/public/serve/icons/font.png +0 -0
- package/server/public/serve/icons/image.png +0 -0
- package/server/public/serve/icons/map.png +0 -0
- package/server/public/serve/icons/page.png +0 -0
- package/server/public/serve/icons/page_add.png +0 -0
- package/server/public/serve/icons/page_attach.png +0 -0
- package/server/public/serve/icons/page_code.png +0 -0
- package/server/public/serve/icons/page_copy.png +0 -0
- package/server/public/serve/icons/page_delete.png +0 -0
- package/server/public/serve/icons/page_edit.png +0 -0
- package/server/public/serve/icons/page_error.png +0 -0
- package/server/public/serve/icons/page_excel.png +0 -0
- package/server/public/serve/icons/page_find.png +0 -0
- package/server/public/serve/icons/page_gear.png +0 -0
- package/server/public/serve/icons/page_go.png +0 -0
- package/server/public/serve/icons/page_green.png +0 -0
- package/server/public/serve/icons/page_key.png +0 -0
- package/server/public/serve/icons/page_lightning.png +0 -0
- package/server/public/serve/icons/page_link.png +0 -0
- package/server/public/serve/icons/page_paintbrush.png +0 -0
- package/server/public/serve/icons/page_paste.png +0 -0
- package/server/public/serve/icons/page_red.png +0 -0
- package/server/public/serve/icons/page_refresh.png +0 -0
- package/server/public/serve/icons/page_save.png +0 -0
- package/server/public/serve/icons/page_white.png +0 -0
- package/server/public/serve/icons/page_white_acrobat.png +0 -0
- package/server/public/serve/icons/page_white_actionscript.png +0 -0
- package/server/public/serve/icons/page_white_add.png +0 -0
- package/server/public/serve/icons/page_white_c.png +0 -0
- package/server/public/serve/icons/page_white_camera.png +0 -0
- package/server/public/serve/icons/page_white_cd.png +0 -0
- package/server/public/serve/icons/page_white_code.png +0 -0
- package/server/public/serve/icons/page_white_code_red.png +0 -0
- package/server/public/serve/icons/page_white_coldfusion.png +0 -0
- package/server/public/serve/icons/page_white_compressed.png +0 -0
- package/server/public/serve/icons/page_white_copy.png +0 -0
- package/server/public/serve/icons/page_white_cplusplus.png +0 -0
- package/server/public/serve/icons/page_white_csharp.png +0 -0
- package/server/public/serve/icons/page_white_cup.png +0 -0
- package/server/public/serve/icons/page_white_database.png +0 -0
- package/server/public/serve/icons/page_white_delete.png +0 -0
- package/server/public/serve/icons/page_white_dvd.png +0 -0
- package/server/public/serve/icons/page_white_edit.png +0 -0
- package/server/public/serve/icons/page_white_error.png +0 -0
- package/server/public/serve/icons/page_white_excel.png +0 -0
- package/server/public/serve/icons/page_white_find.png +0 -0
- package/server/public/serve/icons/page_white_flash.png +0 -0
- package/server/public/serve/icons/page_white_freehand.png +0 -0
- package/server/public/serve/icons/page_white_gear.png +0 -0
- package/server/public/serve/icons/page_white_get.png +0 -0
- package/server/public/serve/icons/page_white_go.png +0 -0
- package/server/public/serve/icons/page_white_h.png +0 -0
- package/server/public/serve/icons/page_white_horizontal.png +0 -0
- package/server/public/serve/icons/page_white_key.png +0 -0
- package/server/public/serve/icons/page_white_lightning.png +0 -0
- package/server/public/serve/icons/page_white_link.png +0 -0
- package/server/public/serve/icons/page_white_magnify.png +0 -0
- package/server/public/serve/icons/page_white_medal.png +0 -0
- package/server/public/serve/icons/page_white_office.png +0 -0
- package/server/public/serve/icons/page_white_paint.png +0 -0
- package/server/public/serve/icons/page_white_paintbrush.png +0 -0
- package/server/public/serve/icons/page_white_paste.png +0 -0
- package/server/public/serve/icons/page_white_php.png +0 -0
- package/server/public/serve/icons/page_white_picture.png +0 -0
- package/server/public/serve/icons/page_white_powerpoint.png +0 -0
- package/server/public/serve/icons/page_white_put.png +0 -0
- package/server/public/serve/icons/page_white_ruby.png +0 -0
- package/server/public/serve/icons/page_white_stack.png +0 -0
- package/server/public/serve/icons/page_white_star.png +0 -0
- package/server/public/serve/icons/page_white_swoosh.png +0 -0
- package/server/public/serve/icons/page_white_text.png +0 -0
- package/server/public/serve/icons/page_white_text_width.png +0 -0
- package/server/public/serve/icons/page_white_tux.png +0 -0
- package/server/public/serve/icons/page_white_vector.png +0 -0
- package/server/public/serve/icons/page_white_visualstudio.png +0 -0
- package/server/public/serve/icons/page_white_width.png +0 -0
- package/server/public/serve/icons/page_white_word.png +0 -0
- package/server/public/serve/icons/page_white_world.png +0 -0
- package/server/public/serve/icons/page_white_wrench.png +0 -0
- package/server/public/serve/icons/page_white_zip.png +0 -0
- package/server/public/serve/icons/page_word.png +0 -0
- package/server/public/serve/icons/page_world.png +0 -0
- package/server/public/serve/style.css +308 -0
- package/server/public/style.css +13 -5
- package/server/public/urldropdown.css +95 -3
- package/server/public/urldropdown.js +245 -23
- package/server/serveIndex.js +691 -0
- package/server/views/app.ejs +305 -89
- package/server/views/connect.ejs +3 -0
- package/server/views/container.ejs +2 -1
- package/server/views/index.ejs +3 -0
- package/server/views/init/index.ejs +3 -0
- package/server/views/net.ejs +30 -27
- package/server/views/network.ejs +23 -70
- package/server/views/screenshots.ejs +3 -0
- package/server/views/settings.ejs +3 -0
- package/server/views/tools.ejs +3 -0
|
@@ -55,6 +55,31 @@ function initUrlDropdown(config = {}) {
|
|
|
55
55
|
}
|
|
56
56
|
});
|
|
57
57
|
|
|
58
|
+
if (document.querySelector(".urlbar")) {
|
|
59
|
+
document.querySelector(".urlbar").addEventListener("submit", (e) => {
|
|
60
|
+
e.preventDefault()
|
|
61
|
+
e.stopPropagation()
|
|
62
|
+
let el = e.target.querySelector("input[type=url]")
|
|
63
|
+
let val = el.value
|
|
64
|
+
let type = el.getAttribute("data-host-type")
|
|
65
|
+
if (type === "local") {
|
|
66
|
+
let redirect_uri = "/container?url=" + val
|
|
67
|
+
location.href = redirect_uri
|
|
68
|
+
} else {
|
|
69
|
+
let u = new URL(val)
|
|
70
|
+
if (String(u.port) === "42000") {
|
|
71
|
+
// pinokio app => open the url itself
|
|
72
|
+
window.open(val, "_blank")
|
|
73
|
+
} else {
|
|
74
|
+
// other servers => open in pinokio redirect frame
|
|
75
|
+
let redirect_uri = "/container?url=" + val
|
|
76
|
+
location.href = redirect_uri
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
58
83
|
function initializeInputValue() {
|
|
59
84
|
if (options.clearBehavior === 'empty') {
|
|
60
85
|
urlInput.value = '';
|
|
@@ -140,6 +165,111 @@ function initUrlDropdown(config = {}) {
|
|
|
140
165
|
dropdown.style.display = 'none';
|
|
141
166
|
}
|
|
142
167
|
|
|
168
|
+
function createHostBadge(host) {
|
|
169
|
+
if (!host || !host.platform) return '';
|
|
170
|
+
|
|
171
|
+
// Get platform icon
|
|
172
|
+
let platformIcon = '';
|
|
173
|
+
switch (host.platform) {
|
|
174
|
+
case 'darwin':
|
|
175
|
+
platformIcon = 'fa-brands fa-apple';
|
|
176
|
+
break;
|
|
177
|
+
case 'win32':
|
|
178
|
+
platformIcon = 'fa-brands fa-windows';
|
|
179
|
+
break;
|
|
180
|
+
case 'linux':
|
|
181
|
+
platformIcon = 'fa-brands fa-linux';
|
|
182
|
+
break;
|
|
183
|
+
default:
|
|
184
|
+
platformIcon = 'fa-solid fa-desktop';
|
|
185
|
+
break;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Create badge HTML
|
|
189
|
+
return `
|
|
190
|
+
<span class="host-badge">
|
|
191
|
+
<i class="${platformIcon}"></i>
|
|
192
|
+
<span class="host-name">${escapeHtml(host.name)}</span>
|
|
193
|
+
</span>
|
|
194
|
+
`;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function groupProcessesByHost(processes) {
|
|
198
|
+
const grouped = {};
|
|
199
|
+
|
|
200
|
+
processes.forEach(process => {
|
|
201
|
+
// Create a normalized host key based only on name for grouping
|
|
202
|
+
const hostKey = process.host ? process.host.name : 'Unknown';
|
|
203
|
+
|
|
204
|
+
if (!grouped[hostKey]) {
|
|
205
|
+
grouped[hostKey] = {
|
|
206
|
+
host: process.host || { name: 'Unknown', platform: 'unknown', arch: 'unknown' },
|
|
207
|
+
processes: [],
|
|
208
|
+
isLocal: false
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Mark as local if any process from this host is local
|
|
213
|
+
if (process.host.local === true) {
|
|
214
|
+
grouped[hostKey].isLocal = true;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
grouped[hostKey].processes.push(process);
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
// Sort host keys: local host first, then alphabetically
|
|
221
|
+
return Object.keys(grouped)
|
|
222
|
+
.sort((a, b) => {
|
|
223
|
+
const aIsLocal = grouped[a].isLocal;
|
|
224
|
+
const bIsLocal = grouped[b].isLocal;
|
|
225
|
+
|
|
226
|
+
// Local host always comes first
|
|
227
|
+
if (aIsLocal && !bIsLocal) return 1;
|
|
228
|
+
if (!aIsLocal && bIsLocal) return -1;
|
|
229
|
+
|
|
230
|
+
// Both local or both remote - sort alphabetically
|
|
231
|
+
return a.localeCompare(b);
|
|
232
|
+
})
|
|
233
|
+
.reduce((sortedGrouped, hostKey) => {
|
|
234
|
+
sortedGrouped[hostKey] = grouped[hostKey];
|
|
235
|
+
return sortedGrouped;
|
|
236
|
+
}, {});
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function createHostHeader(host, isLocal = false) {
|
|
240
|
+
if (!host) return '';
|
|
241
|
+
|
|
242
|
+
// Get platform icon
|
|
243
|
+
let platformIcon = '';
|
|
244
|
+
switch (host.platform) {
|
|
245
|
+
case 'darwin':
|
|
246
|
+
platformIcon = 'fa-brands fa-apple';
|
|
247
|
+
break;
|
|
248
|
+
case 'win32':
|
|
249
|
+
platformIcon = 'fa-brands fa-windows';
|
|
250
|
+
break;
|
|
251
|
+
case 'linux':
|
|
252
|
+
platformIcon = 'fa-brands fa-linux';
|
|
253
|
+
break;
|
|
254
|
+
default:
|
|
255
|
+
platformIcon = 'fa-solid fa-desktop';
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
console.log({ isLocal, host })
|
|
260
|
+
const hostName = isLocal ? `${host.name} (This Machine)` : `${host.name} (Peer)`;
|
|
261
|
+
|
|
262
|
+
return `
|
|
263
|
+
<div class="url-dropdown-host-header">
|
|
264
|
+
<span class='host-meta'>
|
|
265
|
+
<i class="${platformIcon}"></i>
|
|
266
|
+
<span class="host-arch">${escapeHtml(host.arch)}</span>
|
|
267
|
+
</span>
|
|
268
|
+
<span class="host-name">${escapeHtml(hostName)}</span>
|
|
269
|
+
</div>
|
|
270
|
+
`;
|
|
271
|
+
}
|
|
272
|
+
|
|
143
273
|
function populateDropdown(processes) {
|
|
144
274
|
if (processes.length === 0) {
|
|
145
275
|
const query = urlInput.value.toLowerCase().trim();
|
|
@@ -150,28 +280,76 @@ function initUrlDropdown(config = {}) {
|
|
|
150
280
|
return;
|
|
151
281
|
}
|
|
152
282
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
283
|
+
// Group processes by host
|
|
284
|
+
const groupedProcesses = groupProcessesByHost(processes);
|
|
285
|
+
|
|
286
|
+
let html = '';
|
|
287
|
+
Object.keys(groupedProcesses).forEach(hostKey => {
|
|
288
|
+
const hostData = groupedProcesses[hostKey];
|
|
289
|
+
const hostInfo = hostData.host;
|
|
290
|
+
const processes = hostData.processes;
|
|
291
|
+
const isLocal = hostData.isLocal;
|
|
292
|
+
|
|
293
|
+
// Add host header
|
|
294
|
+
html += createHostHeader(hostInfo, isLocal);
|
|
295
|
+
|
|
296
|
+
// Add processes for this host
|
|
297
|
+
processes.forEach(process => {
|
|
298
|
+
const onlineIndicator = process.online ?
|
|
299
|
+
'<div class="status-circle online"></div>' :
|
|
300
|
+
'<div class="status-circle offline"></div>';
|
|
301
|
+
|
|
302
|
+
if (process.ip === null || process.ip === undefined) {
|
|
303
|
+
// Non-selectable item with "turn on peer network" button
|
|
304
|
+
const networkUrl = `http://${process.host.ip}:42000/network`;
|
|
305
|
+
html += `
|
|
306
|
+
<div class="url-dropdown-item non-selectable">
|
|
307
|
+
<div class="url-dropdown-name">
|
|
308
|
+
${onlineIndicator}
|
|
309
|
+
<button class="peer-network-button" data-network-url="${networkUrl}"><i class="fa-solid fa-toggle-on"></i> Turn on peer network</button>
|
|
310
|
+
${escapeHtml(process.name)}
|
|
311
|
+
</div>
|
|
312
|
+
</div>
|
|
313
|
+
`;
|
|
314
|
+
} else {
|
|
315
|
+
// Normal selectable item
|
|
316
|
+
const url = `http://${process.ip}`;
|
|
317
|
+
html += `
|
|
318
|
+
<div class="url-dropdown-item" data-url="${url}" data-host-type="${process.host.local ? "local" : "remote"}">
|
|
319
|
+
<div class="url-dropdown-name">
|
|
320
|
+
${onlineIndicator}
|
|
321
|
+
${escapeHtml(process.name)}
|
|
322
|
+
</div>
|
|
323
|
+
<div class="url-dropdown-url">${escapeHtml(url)}</div>
|
|
324
|
+
</div>
|
|
325
|
+
`;
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
});
|
|
162
329
|
|
|
163
|
-
dropdown.innerHTML =
|
|
330
|
+
dropdown.innerHTML = html;
|
|
164
331
|
|
|
165
332
|
// Add click handlers to dropdown items
|
|
166
|
-
dropdown.querySelectorAll('.url-dropdown-item').forEach(item => {
|
|
333
|
+
dropdown.querySelectorAll('.url-dropdown-item:not(.non-selectable)').forEach(item => {
|
|
167
334
|
item.addEventListener('click', function() {
|
|
168
335
|
const url = this.getAttribute('data-url');
|
|
336
|
+
const type = this.getAttribute('data-host-type');
|
|
169
337
|
urlInput.value = url;
|
|
338
|
+
urlInput.setAttribute("data-host-type", type)
|
|
170
339
|
hideDropdown();
|
|
171
340
|
// Submit the form
|
|
172
341
|
urlInput.closest('form').dispatchEvent(new Event('submit'));
|
|
173
342
|
});
|
|
174
343
|
});
|
|
344
|
+
|
|
345
|
+
// Add click handlers to peer network buttons
|
|
346
|
+
dropdown.querySelectorAll('.peer-network-button').forEach(button => {
|
|
347
|
+
button.addEventListener('click', function(e) {
|
|
348
|
+
e.stopPropagation();
|
|
349
|
+
const networkUrl = this.getAttribute('data-network-url');
|
|
350
|
+
window.open(networkUrl, '_blank');
|
|
351
|
+
});
|
|
352
|
+
});
|
|
175
353
|
}
|
|
176
354
|
|
|
177
355
|
// Utility function to escape HTML
|
|
@@ -330,19 +508,54 @@ function initUrlDropdown(config = {}) {
|
|
|
330
508
|
return;
|
|
331
509
|
}
|
|
332
510
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
511
|
+
// Group processes by host
|
|
512
|
+
const groupedProcesses = groupProcessesByHost(processes);
|
|
513
|
+
|
|
514
|
+
let html = '';
|
|
515
|
+
Object.keys(groupedProcesses).forEach(hostKey => {
|
|
516
|
+
const hostData = groupedProcesses[hostKey];
|
|
517
|
+
const hostInfo = hostData.host;
|
|
518
|
+
const processes = hostData.processes;
|
|
519
|
+
const isLocal = hostData.isLocal;
|
|
520
|
+
|
|
521
|
+
// Add host header
|
|
522
|
+
html += createHostHeader(hostInfo, isLocal);
|
|
523
|
+
|
|
524
|
+
// Add processes for this host
|
|
525
|
+
processes.forEach(process => {
|
|
526
|
+
const onlineIndicator = process.online ?
|
|
527
|
+
'<div class="status-circle online"></div>' :
|
|
528
|
+
'<div class="status-circle offline"></div>';
|
|
529
|
+
|
|
530
|
+
if (process.ip === null || process.ip === undefined) {
|
|
531
|
+
// Non-selectable item with "turn on peer network" button
|
|
532
|
+
const networkUrl = `http://${process.host.ip}:42000/network`;
|
|
533
|
+
html += `
|
|
534
|
+
<div class="url-dropdown-item non-selectable">
|
|
535
|
+
<div class="url-dropdown-name">
|
|
536
|
+
${onlineIndicator}
|
|
537
|
+
${escapeHtml(process.name)}
|
|
538
|
+
</div>
|
|
539
|
+
<button class="peer-network-button" data-network-url="${networkUrl}"><i class="fa-solid fa-toggle-on"></i> Turn on peer network</button>
|
|
540
|
+
</div>
|
|
541
|
+
`;
|
|
542
|
+
} else {
|
|
543
|
+
// Normal selectable item
|
|
544
|
+
const url = `http://${process.ip}`;
|
|
545
|
+
html += `
|
|
546
|
+
<div class="url-dropdown-item" data-url="${url}" data-host-type="${process.host.local ? "local" : "remote"}">
|
|
547
|
+
${onlineIndicator}
|
|
548
|
+
<div class="url-dropdown-name">${escapeHtml(process.name)}</div>
|
|
549
|
+
<div class="url-dropdown-url">${escapeHtml(url)}</div>
|
|
550
|
+
</div>
|
|
551
|
+
`;
|
|
552
|
+
}
|
|
553
|
+
});
|
|
554
|
+
});
|
|
342
555
|
|
|
343
|
-
modalDropdown.innerHTML =
|
|
556
|
+
modalDropdown.innerHTML = html;
|
|
344
557
|
|
|
345
|
-
modalDropdown.querySelectorAll('.url-dropdown-item').forEach(item => {
|
|
558
|
+
modalDropdown.querySelectorAll('.url-dropdown-item:not(.non-selectable)').forEach(item => {
|
|
346
559
|
item.addEventListener('click', function() {
|
|
347
560
|
const url = this.getAttribute('data-url');
|
|
348
561
|
modalInput.value = url;
|
|
@@ -351,6 +564,15 @@ function initUrlDropdown(config = {}) {
|
|
|
351
564
|
closeMobileModal();
|
|
352
565
|
});
|
|
353
566
|
});
|
|
567
|
+
|
|
568
|
+
// Add click handlers to peer network buttons in modal
|
|
569
|
+
modalDropdown.querySelectorAll('.peer-network-button').forEach(button => {
|
|
570
|
+
button.addEventListener('click', function(e) {
|
|
571
|
+
e.stopPropagation();
|
|
572
|
+
const networkUrl = this.getAttribute('data-network-url');
|
|
573
|
+
window.open(networkUrl, '_blank');
|
|
574
|
+
});
|
|
575
|
+
});
|
|
354
576
|
}
|
|
355
577
|
|
|
356
578
|
// Set up mobile button click handler
|
|
@@ -393,4 +615,4 @@ if (document.readyState === 'loading') {
|
|
|
393
615
|
});
|
|
394
616
|
} else {
|
|
395
617
|
// DOM is already loaded, templates can initialize immediately
|
|
396
|
-
}
|
|
618
|
+
}
|