pinokiod 3.9.28 → 3.9.30
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/api/index.js +0 -20
- package/kernel/api/input/index.js +2 -1
- package/kernel/api/shell/index.js +1 -1
- package/kernel/bin/index.js +0 -15
- package/kernel/index.js +9 -31
- package/kernel/loader.js +1 -0
- package/kernel/plugin.js +2 -2
- package/kernel/prototype.js +28 -23
- package/kernel/shells.js +6 -2
- package/package.json +1 -1
- package/server/index.js +111 -32
- package/server/public/fseditor.js +2 -9
- package/server/public/modalinput.js +28 -9
- package/server/public/opener.js +0 -1
- package/server/public/style.css +44 -5
- package/server/views/app.ejs +50 -40
- package/server/views/connect.ejs +96 -13
- package/server/views/network.ejs +4 -2
- package/server/views/partials/dynamic.ejs +3 -5
- package/server/views/partials/menu.ejs +1 -1
- package/server/views/prototype/index.ejs +967 -310
- package/server/views/prototype/old_index.ejs +646 -0
- package/server/views/prototype/show.ejs +11 -158
- package/server/views/settings.ejs +6 -3
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
<html>
|
|
2
2
|
<head>
|
|
3
|
-
<title
|
|
3
|
+
<title><%=config.title%></title>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
|
|
6
|
-
<link href="/xterm.min.css" rel="stylesheet" />
|
|
7
6
|
<link href="/css/fontawesome.min.css" rel="stylesheet">
|
|
8
7
|
<link href="/css/solid.min.css" rel="stylesheet">
|
|
9
8
|
<link href="/css/regular.min.css" rel="stylesheet">
|
|
@@ -18,191 +17,6 @@
|
|
|
18
17
|
<link href="/electron.css" rel="stylesheet"/>
|
|
19
18
|
<% } %>
|
|
20
19
|
<style>
|
|
21
|
-
.line2 {
|
|
22
|
-
display: flex;
|
|
23
|
-
align-items: center;
|
|
24
|
-
cursor: pointer;
|
|
25
|
-
background: rgba(0,0,100,0.04);
|
|
26
|
-
}
|
|
27
|
-
.line2 a {
|
|
28
|
-
text-decoration: none;
|
|
29
|
-
color: black;
|
|
30
|
-
}
|
|
31
|
-
.status {
|
|
32
|
-
padding: 10px;
|
|
33
|
-
margin: 10px;
|
|
34
|
-
border-radius: 10px;
|
|
35
|
-
}
|
|
36
|
-
.status.offline {
|
|
37
|
-
background: silver;
|
|
38
|
-
}
|
|
39
|
-
.status.online {
|
|
40
|
-
background: yellowgreen;
|
|
41
|
-
}
|
|
42
|
-
.switch {
|
|
43
|
-
padding: 10px;
|
|
44
|
-
margin: 10px 0;
|
|
45
|
-
}
|
|
46
|
-
.switch[data-online=true] {
|
|
47
|
-
color: yellowgreen;
|
|
48
|
-
}
|
|
49
|
-
.button {
|
|
50
|
-
padding: 10px;
|
|
51
|
-
}
|
|
52
|
-
.on, .off {
|
|
53
|
-
display: flex;
|
|
54
|
-
align-items: center;
|
|
55
|
-
}
|
|
56
|
-
header .runner {
|
|
57
|
-
padding: 10px 0 0;
|
|
58
|
-
}
|
|
59
|
-
.proxy {
|
|
60
|
-
padding: 0 10px;
|
|
61
|
-
text-align: right;
|
|
62
|
-
}
|
|
63
|
-
.proxy a {
|
|
64
|
-
text-decoration: none;
|
|
65
|
-
display: inline-block;
|
|
66
|
-
padding: 5px 10px;
|
|
67
|
-
border-radius: 2px;
|
|
68
|
-
background: black;
|
|
69
|
-
color: white;
|
|
70
|
-
}
|
|
71
|
-
.browser-options-btns {
|
|
72
|
-
display: flex;
|
|
73
|
-
padding-top: 5px;
|
|
74
|
-
}
|
|
75
|
-
.browser-options-row {
|
|
76
|
-
/*
|
|
77
|
-
border-top: 1px solid rgba(0,0,0,0.1);
|
|
78
|
-
border-bottom: 1px solid rgba(0,0,0,0.1);
|
|
79
|
-
*/
|
|
80
|
-
display: flex;
|
|
81
|
-
padding: 10px;
|
|
82
|
-
align-items: flex-start;
|
|
83
|
-
}
|
|
84
|
-
.browser-options-row h3 {
|
|
85
|
-
margin: 0;
|
|
86
|
-
font-size: 14px;
|
|
87
|
-
margin-bottom: 3px;
|
|
88
|
-
}
|
|
89
|
-
.browser-options-row .btn.disabled {
|
|
90
|
-
opacity: 0.7;
|
|
91
|
-
}
|
|
92
|
-
.browser-options-row .btn {
|
|
93
|
-
font-weight: bold;
|
|
94
|
-
width: 100px;
|
|
95
|
-
text-align: center;
|
|
96
|
-
display: block;
|
|
97
|
-
margin-right: 10px;
|
|
98
|
-
flex-shrink: 0;
|
|
99
|
-
padding: 5px;
|
|
100
|
-
}
|
|
101
|
-
.badge {
|
|
102
|
-
font-size: 12px;
|
|
103
|
-
padding: 5px 10px;
|
|
104
|
-
background: rgba(0,0,100,0.1);
|
|
105
|
-
border-radius: 5px;
|
|
106
|
-
display: inline-block;
|
|
107
|
-
margin-top: 5px;
|
|
108
|
-
}
|
|
109
|
-
a.badge {
|
|
110
|
-
color: royalblue;
|
|
111
|
-
text-decoration: none;
|
|
112
|
-
cursor: pointer;
|
|
113
|
-
}
|
|
114
|
-
.badge a {
|
|
115
|
-
color: royalblue;
|
|
116
|
-
text-decoration: none;
|
|
117
|
-
}
|
|
118
|
-
body.dark .btn {
|
|
119
|
-
color: white;
|
|
120
|
-
border: 1px solid rgba(255,255,255,0.3);
|
|
121
|
-
}
|
|
122
|
-
body.dark .badge {
|
|
123
|
-
background: rgba(255,255,255,0.1);
|
|
124
|
-
}
|
|
125
|
-
.folder-templates {
|
|
126
|
-
background: rgba(0,0,100, 0.02);
|
|
127
|
-
}
|
|
128
|
-
.folder-templates .folder {
|
|
129
|
-
text-decoration: none;
|
|
130
|
-
color: rgba(0,0,0,0.9);
|
|
131
|
-
font-size: 12px;
|
|
132
|
-
padding: 10px;
|
|
133
|
-
display: flex;
|
|
134
|
-
align-items: center;
|
|
135
|
-
}
|
|
136
|
-
.folder-templates .folder .title {
|
|
137
|
-
font-weight: bold;
|
|
138
|
-
font-size: 15px;
|
|
139
|
-
text-transform: capitalize;
|
|
140
|
-
}
|
|
141
|
-
.folder-templates .folder img {
|
|
142
|
-
width: 30px;
|
|
143
|
-
height: 30px;
|
|
144
|
-
margin-right: 10px;
|
|
145
|
-
border-radius: 10px;
|
|
146
|
-
}
|
|
147
|
-
body.dark .prototype-header {
|
|
148
|
-
color: white;
|
|
149
|
-
}
|
|
150
|
-
.prototype-header .btn {
|
|
151
|
-
border: 1px solid rgba(255,255,255,0.3);
|
|
152
|
-
}
|
|
153
|
-
.prototype-header {
|
|
154
|
-
align-items: center;
|
|
155
|
-
display: flex;
|
|
156
|
-
padding: 40px 20px;
|
|
157
|
-
}
|
|
158
|
-
.prototype-header h1 {
|
|
159
|
-
letter-spacing: -1px;
|
|
160
|
-
}
|
|
161
|
-
.prototype-header .desc {
|
|
162
|
-
color: silver;
|
|
163
|
-
}
|
|
164
|
-
/*
|
|
165
|
-
body.dark .browser-options-row {
|
|
166
|
-
border-top: 1px solid rgba(255,255,255,0.05);
|
|
167
|
-
border-bottom: 1px solid rgba(255,255,255,0.05);
|
|
168
|
-
}
|
|
169
|
-
*/
|
|
170
|
-
.meta {
|
|
171
|
-
display: flex;
|
|
172
|
-
align-items: flex-start;
|
|
173
|
-
padding: 20px;
|
|
174
|
-
}
|
|
175
|
-
.meta-content {
|
|
176
|
-
padding: 10px;
|
|
177
|
-
}
|
|
178
|
-
.meta-content h2 {
|
|
179
|
-
margin: 0;
|
|
180
|
-
font-size: 30px;
|
|
181
|
-
}
|
|
182
|
-
.meta-path {
|
|
183
|
-
padding: 10px 0;
|
|
184
|
-
opacity: 0.7;
|
|
185
|
-
}
|
|
186
|
-
.meta img {
|
|
187
|
-
width: 100px;
|
|
188
|
-
}
|
|
189
|
-
@media only screen and (max-width: 480px) {
|
|
190
|
-
.btn2 {
|
|
191
|
-
padding: 5px;
|
|
192
|
-
font-size: 11px;
|
|
193
|
-
}
|
|
194
|
-
.nav-btns {
|
|
195
|
-
flex-grow: 1;
|
|
196
|
-
justify-content: center;
|
|
197
|
-
padding: 0;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
20
|
.online {
|
|
207
21
|
width: 10px;
|
|
208
22
|
height: 10px;
|
|
@@ -292,6 +106,11 @@ main iframe {
|
|
|
292
106
|
height: 100%;
|
|
293
107
|
border: none;
|
|
294
108
|
}
|
|
109
|
+
/*
|
|
110
|
+
.header-item.indent {
|
|
111
|
+
padding-left: 23px !important;
|
|
112
|
+
}
|
|
113
|
+
*/
|
|
295
114
|
.header-item {
|
|
296
115
|
/*
|
|
297
116
|
display: block;
|
|
@@ -308,7 +127,6 @@ main iframe {
|
|
|
308
127
|
.header-item .btn2 {
|
|
309
128
|
margin: 0;
|
|
310
129
|
border: none;
|
|
311
|
-
padding: 5px;
|
|
312
130
|
/*
|
|
313
131
|
color: var(--light-color);
|
|
314
132
|
*/
|
|
@@ -347,7 +165,7 @@ body.dark .header-item.btn {
|
|
|
347
165
|
color: var(--dark-color);
|
|
348
166
|
}
|
|
349
167
|
.header-item.btn {
|
|
350
|
-
padding:
|
|
168
|
+
padding: 8px;
|
|
351
169
|
background: none !important;
|
|
352
170
|
color: var(--light-color);
|
|
353
171
|
}
|
|
@@ -378,6 +196,9 @@ body.dark #new-window {
|
|
|
378
196
|
background: rgba(255,255,255,0.04);
|
|
379
197
|
}
|
|
380
198
|
*/
|
|
199
|
+
.app-info-card img {
|
|
200
|
+
padding: 10px;
|
|
201
|
+
}
|
|
381
202
|
.app-info {
|
|
382
203
|
|
|
383
204
|
/*
|
|
@@ -396,12 +217,6 @@ body.dark #new-window {
|
|
|
396
217
|
grid-template-columns: repeat(4, 1fr);
|
|
397
218
|
gap: 0px;
|
|
398
219
|
}
|
|
399
|
-
.header-btns {
|
|
400
|
-
padding: 0 !important;
|
|
401
|
-
}
|
|
402
|
-
body.dark .header-btns {
|
|
403
|
-
border-top: 1px solid rgba(255,255,255,0.04);
|
|
404
|
-
}
|
|
405
220
|
.app-info-edit {
|
|
406
221
|
text-decoration: none;
|
|
407
222
|
color: black;
|
|
@@ -435,13 +250,45 @@ body.dark .header-btns {
|
|
|
435
250
|
*/
|
|
436
251
|
}
|
|
437
252
|
.app-info-card {
|
|
253
|
+
/*
|
|
438
254
|
padding: 10px !important;
|
|
255
|
+
*/
|
|
256
|
+
display: flex;
|
|
439
257
|
}
|
|
440
258
|
.app-info .btn {
|
|
441
259
|
width: 100%;
|
|
260
|
+
box-sizing: border-box;
|
|
261
|
+
}
|
|
262
|
+
body.dark .app-info .mode-section {
|
|
263
|
+
background: rgba(0,0,0,0.4);
|
|
264
|
+
}
|
|
265
|
+
.app-info .mode-section {
|
|
266
|
+
background: rgba(0,0,0,0.06);
|
|
267
|
+
padding: 20px;
|
|
268
|
+
box-sizing: border-box;
|
|
269
|
+
width: 100%;
|
|
270
|
+
text-align: left;
|
|
271
|
+
}
|
|
272
|
+
.app-info .mode-section .desc {
|
|
273
|
+
font-weight: normal;
|
|
274
|
+
opacity: 0.7;
|
|
275
|
+
}
|
|
276
|
+
.app-info .mode-section h3 {
|
|
277
|
+
font-size: 18px;
|
|
278
|
+
line-height: 26px;
|
|
279
|
+
margin: 0;
|
|
280
|
+
}
|
|
281
|
+
body.dark .app-info .mode-section .btn {
|
|
282
|
+
border: 1px solid rgba(255,255,255,0.1);
|
|
283
|
+
}
|
|
284
|
+
.app-info .mode-section .btn {
|
|
285
|
+
margin-top: 10px;
|
|
286
|
+
text-align: center;
|
|
442
287
|
}
|
|
443
288
|
.app-info-card > * {
|
|
289
|
+
/*
|
|
444
290
|
padding: 5px;
|
|
291
|
+
*/
|
|
445
292
|
color: var(--light-color);
|
|
446
293
|
text-decoration: none;
|
|
447
294
|
box-sizing: border-box;
|
|
@@ -449,7 +296,346 @@ body.dark .header-btns {
|
|
|
449
296
|
body.dark .app-info-card > * {
|
|
450
297
|
color: var(--dark-color);
|
|
451
298
|
}
|
|
299
|
+
.app-info-title {
|
|
300
|
+
padding: 15px 0;
|
|
301
|
+
}
|
|
302
|
+
.footer {
|
|
303
|
+
/*
|
|
304
|
+
display: flex;
|
|
305
|
+
*/
|
|
306
|
+
display: grid;
|
|
307
|
+
grid-template-columns: repeat(4, 1fr);
|
|
308
|
+
}
|
|
309
|
+
.footer > * {
|
|
310
|
+
padding: 10px !important;
|
|
311
|
+
display: block;
|
|
312
|
+
box-sizing: border-box;
|
|
313
|
+
font-size: 12px !important;
|
|
314
|
+
text-align: center;
|
|
315
|
+
}
|
|
316
|
+
.footer i {
|
|
317
|
+
margin: 0 !important;
|
|
318
|
+
padding: 5px;
|
|
319
|
+
}
|
|
320
|
+
.footer a {
|
|
321
|
+
font-size: 14px;
|
|
322
|
+
}
|
|
323
|
+
body .footer {
|
|
324
|
+
border-bottom: 1px solid rgba(0,0,0,0.04);
|
|
325
|
+
}
|
|
326
|
+
body.dark .footer {
|
|
327
|
+
border-bottom: 1px solid rgba(255,255,255,0.04);
|
|
328
|
+
}
|
|
329
|
+
body.dark .header-item.cursor {
|
|
330
|
+
background: rgba(0,0,0, 0.2) !important;
|
|
331
|
+
}
|
|
332
|
+
.header-item.cursor {
|
|
333
|
+
background: rgba(0,0,100, 0.03) !important;
|
|
334
|
+
/*
|
|
335
|
+
border-left: 5px solid gold;
|
|
336
|
+
*/
|
|
337
|
+
}
|
|
338
|
+
.frame-link {
|
|
339
|
+
cursor: pointer;
|
|
340
|
+
}
|
|
341
|
+
body .frame-link.selected {
|
|
342
|
+
/*
|
|
343
|
+
border-right: 10px solid gold;
|
|
344
|
+
*/
|
|
345
|
+
background: black !important;
|
|
346
|
+
color: white;
|
|
347
|
+
/*
|
|
348
|
+
background: rgba(0,0,100,0.06) !important;
|
|
349
|
+
*/
|
|
350
|
+
}
|
|
351
|
+
.frame-link.selected .del {
|
|
352
|
+
color: white;
|
|
353
|
+
}
|
|
354
|
+
body.dark .frame-link.selected {
|
|
355
|
+
background: rgba(0,0,0,0.7) !important;
|
|
356
|
+
}
|
|
357
|
+
.frame-link .loader {
|
|
358
|
+
/*
|
|
359
|
+
padding: 5px;
|
|
360
|
+
*/
|
|
361
|
+
}
|
|
362
|
+
.loader .btn:hover {
|
|
363
|
+
color: royalblue;
|
|
364
|
+
border-color: royalblue;
|
|
365
|
+
}
|
|
366
|
+
.loader .btn {
|
|
367
|
+
padding: 4px 8px;
|
|
368
|
+
border: 1px solid rgba(255,255,255,0.3);
|
|
369
|
+
}
|
|
370
|
+
.frame-link .tab {
|
|
371
|
+
flex-grow: 1;
|
|
372
|
+
/*
|
|
373
|
+
width: 100%;
|
|
374
|
+
*/
|
|
375
|
+
word-break: break-word;
|
|
376
|
+
/*
|
|
377
|
+
margin-right: 10px;
|
|
378
|
+
*/
|
|
379
|
+
}
|
|
380
|
+
.frame-link .tab .flexible {
|
|
381
|
+
min-width: 5px;
|
|
382
|
+
}
|
|
383
|
+
.frame-link .tab .display {
|
|
384
|
+
word-break: break-word;
|
|
385
|
+
}
|
|
386
|
+
body.dark .grid-btns {
|
|
387
|
+
border-top: 1px solid rgba(255,255,255,0.04);
|
|
388
|
+
border-bottom: 1px solid rgba(255,255,255,0.04);
|
|
389
|
+
}
|
|
390
|
+
.grid-btns {
|
|
391
|
+
border-top: 1px solid rgba(0,0,0,0.04);
|
|
392
|
+
border-bottom: 1px solid rgba(0,0,0,0.04);
|
|
393
|
+
display: grid;
|
|
394
|
+
grid-template-columns: repeat(2, 1fr);
|
|
395
|
+
grid-template-rows: repeat(2, 1fr);
|
|
396
|
+
/*
|
|
397
|
+
grid-template-columns: repeat(3, 1fr);
|
|
398
|
+
grid-template-rows: repeat(1, 1fr);
|
|
399
|
+
*/
|
|
400
|
+
box-sizing: border-box;
|
|
401
|
+
}
|
|
402
|
+
.grid-btns .btn2 {
|
|
403
|
+
padding: 10px 10px;
|
|
404
|
+
color: var(--light-color);
|
|
405
|
+
border-radius: 0;
|
|
406
|
+
cursor: pointer;
|
|
407
|
+
font-size: 11px;
|
|
408
|
+
}
|
|
409
|
+
body.dark .grid-btns .btn2 {
|
|
410
|
+
/*
|
|
411
|
+
color: white;
|
|
412
|
+
*/
|
|
413
|
+
color: var(--dark-btn-color);
|
|
414
|
+
}
|
|
415
|
+
.footer {
|
|
416
|
+
width: 100%;
|
|
417
|
+
}
|
|
418
|
+
.tab {
|
|
419
|
+
flex-grow: 1;
|
|
420
|
+
display: flex;
|
|
421
|
+
align-items: center;
|
|
422
|
+
padding-right: 10px;
|
|
423
|
+
}
|
|
424
|
+
.label i {
|
|
425
|
+
margin-right: 10px;
|
|
426
|
+
}
|
|
427
|
+
.tab i {
|
|
428
|
+
margin-right: 10px;
|
|
429
|
+
font-size: 12px;
|
|
430
|
+
width: 12px;
|
|
431
|
+
}
|
|
432
|
+
.menu-item-image {
|
|
433
|
+
width: 30px !important;
|
|
434
|
+
height: 30px !important;
|
|
435
|
+
padding: 5px;
|
|
436
|
+
border-radius: 40px;
|
|
437
|
+
margin-right: 10px;
|
|
438
|
+
background: white;
|
|
439
|
+
}
|
|
440
|
+
.temp-menu {
|
|
441
|
+
/*
|
|
442
|
+
border-top: 1px solid rgba(0,0,0,0.1);
|
|
443
|
+
*/
|
|
444
|
+
}
|
|
445
|
+
.temp-menu .del i {
|
|
446
|
+
margin: 0;
|
|
447
|
+
}
|
|
448
|
+
#delete {
|
|
449
|
+
color: brown;
|
|
450
|
+
}
|
|
451
|
+
body .footer {
|
|
452
|
+
}
|
|
453
|
+
body.dark nav {
|
|
454
|
+
/*
|
|
455
|
+
border-bottom: 1px solid rgba(255,255,255,0.04);
|
|
456
|
+
*/
|
|
457
|
+
border-top: 1px solid rgba(255,255,255,0.04);
|
|
458
|
+
}
|
|
459
|
+
/*
|
|
460
|
+
.container:hover nav {
|
|
461
|
+
display: block;
|
|
462
|
+
}
|
|
463
|
+
*/
|
|
464
|
+
nav {
|
|
465
|
+
/*
|
|
466
|
+
overflow: hidden;
|
|
467
|
+
max-height: 0;
|
|
468
|
+
transition: max-height 0.4s ease-out;
|
|
469
|
+
display: none;
|
|
470
|
+
*/
|
|
471
|
+
|
|
472
|
+
background: white;
|
|
473
|
+
/*
|
|
474
|
+
position: absolute;
|
|
475
|
+
bottom: 0;
|
|
476
|
+
left: 0;
|
|
477
|
+
right: 0;
|
|
478
|
+
*/
|
|
479
|
+
/*
|
|
480
|
+
padding: 5px;
|
|
481
|
+
*/
|
|
482
|
+
padding: 0;
|
|
483
|
+
cursor: grab !important;
|
|
484
|
+
-webkit-app-region: drag !important;
|
|
485
|
+
/*
|
|
486
|
+
border-bottom: 1px solid rgba(0,0,0,0.04);
|
|
487
|
+
*/
|
|
488
|
+
border-top: 1px solid rgba(0,0,0,0.04);
|
|
489
|
+
box-sizing: border-box;
|
|
490
|
+
}
|
|
491
|
+
body.dark nav .btn2 {
|
|
492
|
+
border-right: 1px solid rgba(255,255,255,0.04);
|
|
493
|
+
}
|
|
494
|
+
nav .btn2 {
|
|
495
|
+
padding: 15px;
|
|
496
|
+
font-size: 12px;
|
|
497
|
+
/*
|
|
498
|
+
width: 70px;
|
|
499
|
+
*/
|
|
500
|
+
box-sizing: border-box;
|
|
501
|
+
border-right: 1px solid rgba(0,0,0,0.04);
|
|
502
|
+
border-radius: 0;
|
|
503
|
+
text-transform: lowercase;
|
|
504
|
+
flex-shrink: 0;
|
|
505
|
+
|
|
506
|
+
display: flex;
|
|
507
|
+
/*
|
|
508
|
+
flex-direction: column;
|
|
509
|
+
*/
|
|
510
|
+
justify-content: center;
|
|
511
|
+
align-items: center;
|
|
512
|
+
}
|
|
513
|
+
nav .logo {
|
|
514
|
+
font-size: 14px;
|
|
515
|
+
padding: 10px;
|
|
516
|
+
}
|
|
517
|
+
.error-message .btn i {
|
|
518
|
+
margin-right: 10px;
|
|
519
|
+
}
|
|
520
|
+
.error-message .btn {
|
|
521
|
+
margin-top: 20px;
|
|
522
|
+
align-items: center;
|
|
523
|
+
display: flex;
|
|
524
|
+
letter-spacing: 0px;
|
|
525
|
+
background: black;
|
|
526
|
+
color: yellow;
|
|
527
|
+
font-size: 20px;
|
|
528
|
+
padding: 10px 30px;
|
|
529
|
+
}
|
|
530
|
+
.error-message {
|
|
531
|
+
display: flex;
|
|
532
|
+
flex-direction: column;
|
|
533
|
+
justify-content: center;
|
|
534
|
+
align-items: center;
|
|
535
|
+
font-weight: bold;
|
|
536
|
+
background: yellow !important;
|
|
537
|
+
flex-grow: 1;
|
|
538
|
+
padding: 0 50px;
|
|
539
|
+
font-size: 40px;
|
|
540
|
+
line-height: 40px;
|
|
541
|
+
color: black;
|
|
542
|
+
letter-spacing: -2px;
|
|
543
|
+
}
|
|
544
|
+
body.dark #location {
|
|
545
|
+
color: white;
|
|
546
|
+
background: rgba(255,255,255,0.03);
|
|
547
|
+
}
|
|
548
|
+
#location {
|
|
549
|
+
background: rgba(0,0,0,0.04);
|
|
550
|
+
padding: 10px;
|
|
551
|
+
margin: 0 10px;
|
|
552
|
+
font-size: 12px;
|
|
553
|
+
font-family: verdana;
|
|
554
|
+
box-sizing: border-box;
|
|
555
|
+
flex-grow: 1;
|
|
556
|
+
border: none;
|
|
557
|
+
outline: none;
|
|
558
|
+
}
|
|
559
|
+
.bar {
|
|
560
|
+
-webkit-app-region: no-drag !important;
|
|
561
|
+
cursor: auto;
|
|
562
|
+
display: flex;
|
|
563
|
+
align-items: stretch;
|
|
564
|
+
width: 100%;
|
|
565
|
+
flex-wrap: wrap;
|
|
566
|
+
}
|
|
567
|
+
body.dark .header-item.cursor.header-top {
|
|
568
|
+
background: none !important;
|
|
569
|
+
}
|
|
570
|
+
.header-item.cursor.header-top {
|
|
571
|
+
background: none !important;
|
|
572
|
+
}
|
|
573
|
+
.header-item.header-top {
|
|
574
|
+
display: block;
|
|
575
|
+
}
|
|
576
|
+
#new-tab:hover {
|
|
577
|
+
background: rgba(0,0,0,0.06) !important;
|
|
578
|
+
color: rgb(200,0,0) !important;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
#new-tab {
|
|
582
|
+
cursor: pointer !important;
|
|
583
|
+
justify-content: center;
|
|
584
|
+
/*
|
|
585
|
+
border-top: 1px solid rgba(0,0,0,0.04);
|
|
586
|
+
*/
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
body.dark #new-tab {
|
|
590
|
+
/*
|
|
591
|
+
border-top: 1px solid rgba(255,255,255,0.04);
|
|
592
|
+
*/
|
|
593
|
+
}
|
|
594
|
+
body.dark .submenu {
|
|
595
|
+
border-left: 1px solid rgba(255,255,255,0.3);
|
|
596
|
+
}
|
|
597
|
+
.submenu {
|
|
598
|
+
border-left: 1px solid black;
|
|
599
|
+
margin-left: 15px;
|
|
600
|
+
box-sizing: border-box;
|
|
601
|
+
}
|
|
602
|
+
#menu-mobile {
|
|
603
|
+
display: none;
|
|
604
|
+
}
|
|
605
|
+
.tabmenu .label {
|
|
606
|
+
padding: 10px;
|
|
607
|
+
border-bottom: 1px solid rgba(255,255,255,0.04);
|
|
608
|
+
text-transform: uppercase;
|
|
609
|
+
font-size: 12px;
|
|
610
|
+
font-weight: bold;
|
|
611
|
+
}
|
|
612
|
+
.disk-usage {
|
|
613
|
+
flex-grow: 1;
|
|
614
|
+
text-align: right;
|
|
615
|
+
font-weight: bold;
|
|
616
|
+
}
|
|
617
|
+
.disk-usage i {
|
|
618
|
+
margin-right: 5px;
|
|
619
|
+
font-size: 16px !important;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
.custom-label {
|
|
624
|
+
position: absolute;
|
|
625
|
+
top: 0;
|
|
626
|
+
left: 0;
|
|
627
|
+
right: 0;
|
|
628
|
+
bottom: 0;
|
|
629
|
+
display: flex;
|
|
630
|
+
align-items: center;
|
|
631
|
+
justify-content: center;
|
|
632
|
+
pointer-events: none; /* Let clicks fall through to FilePond */
|
|
633
|
+
font-size: 14px;
|
|
634
|
+
color: rgba(0, 0, 0, 0.5);
|
|
635
|
+
z-index: 5;
|
|
636
|
+
}
|
|
452
637
|
.appcanvas {
|
|
638
|
+
overflow: auto;
|
|
453
639
|
display: flex;
|
|
454
640
|
flex-grow: 1;
|
|
455
641
|
border-top: 1px solid rgba(0, 0,0 ,0.04);
|
|
@@ -506,31 +692,18 @@ body.dark .appcanvas {
|
|
|
506
692
|
display: flex;
|
|
507
693
|
}
|
|
508
694
|
}
|
|
509
|
-
body.dark .header-item.cursor.header-top {
|
|
510
|
-
background: none !important;
|
|
511
|
-
}
|
|
512
|
-
.header-item.cursor.header-top {
|
|
513
|
-
background: none !important;
|
|
514
|
-
}
|
|
515
|
-
.header-item.header-top {
|
|
516
|
-
display: block;
|
|
517
|
-
}
|
|
518
695
|
</style>
|
|
696
|
+
<link href="/app.css" rel="stylesheet"/>
|
|
519
697
|
<script src="/hotkeys.min.js"></script>
|
|
520
698
|
<script src="/sweetalert2.js"></script>
|
|
521
|
-
<script src="/
|
|
522
|
-
<script src="/notyq.js"></script>
|
|
523
|
-
<script src="/xterm.js"></script>
|
|
524
|
-
<script src="/xterm-addon-fit.js"></script>
|
|
525
|
-
<script src="/xterm-addon-web-links.js"></script>
|
|
526
|
-
<script src="/xterm-theme.js"></script>
|
|
527
|
-
<script src="/Socket.js"></script>
|
|
528
|
-
<script src="/install.js"></script>
|
|
699
|
+
<script src="/nav.js"></script>
|
|
529
700
|
<script src="/common.js"></script>
|
|
530
701
|
<script src="/opener.js"></script>
|
|
531
|
-
<script src="/nav.js"></script>
|
|
532
|
-
<script src="/fuse.js"></script>
|
|
533
702
|
<script src="/report.js"></script>
|
|
703
|
+
<script src="/normalize.js"></script>
|
|
704
|
+
<script src="/Socket.js"></script>
|
|
705
|
+
<script src="/noty.js"></script>
|
|
706
|
+
<script src="/notyq.js"></script>
|
|
534
707
|
<script src="/filepond-plugin-file-validate-type.min.js"></script>
|
|
535
708
|
<script src="/filepond-plugin-image-exif-orientation.min.js"></script>
|
|
536
709
|
<script src="/filepond-plugin-image-preview.min.js"></script>
|
|
@@ -539,108 +712,592 @@ body.dark .header-item.cursor.header-top {
|
|
|
539
712
|
<script src="/filepond-plugin-image-resize.min.js"></script>
|
|
540
713
|
<script src="/filepond-plugin-image-transform.min.js"></script>
|
|
541
714
|
<script src="/filepond.min.js"></script>
|
|
542
|
-
<script src="/
|
|
715
|
+
<script src="/fseditor.js"></script>
|
|
543
716
|
</head>
|
|
544
|
-
<body class='<%=theme%>'>
|
|
545
|
-
<header class='navheader grabbable'>
|
|
546
|
-
<h1>
|
|
547
|
-
<a class='home' href="/"><i class="fa-solid fa-house"></i></a>
|
|
548
|
-
<button class='btn2' id='back'><div><i class="fa-solid fa-chevron-left"></i></div><div>Prev</div></button>
|
|
549
|
-
<button class='btn2' id='forward'><div><i class="fa-solid fa-chevron-right"></i></div><div>Next</div></button>
|
|
550
|
-
<a class='btn2 create-new' id='create-new-folder'><div><i class='fa-solid fa-plus'></i></div><div>New</div></a>
|
|
551
|
-
<a class='btn2' id='explore' href="/?mode=explore"><div><i class="fa-solid fa-magnifying-glass"></i></div><div>Discover</div></a>
|
|
552
|
-
<a href="/network" class='btn2'><div><i class="fa-solid fa-wifi"></i></div><div>Network</div></a>
|
|
553
|
-
<a href="/connect" class='btn2'><div><i class="fa-solid fa-circle-user"></i></div><div>Connect</div></a>
|
|
554
|
-
<div class='flexible'></div>
|
|
555
|
-
<div class='nav-btns'>
|
|
556
|
-
<a href="/network" class='btn2'><div><i class="fa-solid fa-wifi"></i></div><div>Network</div></a>
|
|
557
|
-
<a class='btn2' href="<%=portal%>" target="_blank"><div><i class="fa-solid fa-question"></i></div><div>Help</div></a>
|
|
558
|
-
<button class='btn2' id='genlog'><div><i class="fa-solid fa-laptop-code"></i></div><div>Logs</div></button>
|
|
559
|
-
<a id='downloadlogs' download class='hidden btn2' href="/pinokio/logs.zip"><div><i class="fa-solid fa-download"></i></div><div>Download logs</div></a>
|
|
560
|
-
<a class='btn2' href="/?mode=settings"><div><i class="fa-solid fa-gear"></i></div><div>Settings</div></a>
|
|
561
|
-
<% if (agent === "electron") { %>
|
|
562
|
-
<a href="/" target="_blank" class='btn2' features="browser"><div><i class="fa-solid fa-square-up-right"></i></div><div>Open</div></a>
|
|
563
|
-
<% } else { %>
|
|
564
|
-
<a href="/" target="_blank" class='btn2'><div><i class="fa-solid fa-square-up-right"></i></div><div>Open</div></a>
|
|
565
|
-
<% } %>
|
|
566
|
-
<button id='new-window' title='open a new window' class='btn2'><div><i class="fa-solid fa-plus"></i></div><div>Window</div></button>
|
|
567
|
-
</div>
|
|
568
|
-
</h1>
|
|
569
|
-
</header>
|
|
717
|
+
<body class='<%=theme%>' data-platform="<%=platform%>">
|
|
570
718
|
<div class='appcanvas'>
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
<div class="folderpath"><%=config.web_path%></div>
|
|
582
|
-
</div>
|
|
583
|
-
</div>
|
|
584
|
-
</div>
|
|
585
|
-
</aside>
|
|
586
|
-
<main>
|
|
587
|
-
<div class='container'>
|
|
588
|
-
<div class='prototype-header'>
|
|
589
|
-
<div>
|
|
590
|
-
<h1><%=title%></h1>
|
|
591
|
-
<div class='desc'><%=description%></div>
|
|
592
|
-
</div>
|
|
593
|
-
<div class='flexible'></div>
|
|
594
|
-
<a class='btn' id='download'><i class='fa-solid fa-download'></i> Download a custom prototype script</a>
|
|
595
|
-
</div>
|
|
596
|
-
<div class='folder-templates drawer'>
|
|
597
|
-
<% items.forEach((folder, i) => { %>
|
|
598
|
-
<a class='line folder' href="/prototype/show/<%=folder.id%>?path=<%=path%>">
|
|
599
|
-
<% if (folder.icon) { %>
|
|
600
|
-
<img src="<%=folder.icon%>">
|
|
601
|
-
<% } else { %>
|
|
602
|
-
<% if (theme === 'dark') { %>
|
|
603
|
-
<img src="/pinokio-white.png">
|
|
604
|
-
<% } else { %>
|
|
605
|
-
<img src="/pinokio-black.png">
|
|
606
|
-
<% } %>
|
|
607
|
-
<% } %>
|
|
608
|
-
<div class='col flexible'>
|
|
609
|
-
<div class='title'><%=folder.title%></div>
|
|
610
|
-
<div class='description'><%=folder.description%></div>
|
|
611
|
-
</div>
|
|
612
|
-
</a>
|
|
613
|
-
<% }) %>
|
|
614
|
-
</div>
|
|
615
|
-
</div>
|
|
616
|
-
</main>
|
|
719
|
+
<aside class='active'>
|
|
720
|
+
<div class='m h menu' data-type='h'>
|
|
721
|
+
<% if (config.menu) { %>
|
|
722
|
+
<%- include('./partials/menu', { menu: config.menu, }) %>
|
|
723
|
+
<% } %>
|
|
724
|
+
</div>
|
|
725
|
+
<div class='flexible'></div>
|
|
726
|
+
</aside>
|
|
727
|
+
<div class='container'>
|
|
728
|
+
<main class='browserview'></main>
|
|
617
729
|
</div>
|
|
618
730
|
<script>
|
|
619
|
-
let
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
let
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
list.push({
|
|
626
|
-
index: parseInt(el.getAttribute("data-index")),
|
|
627
|
-
name: el.getAttribute("data-name"),
|
|
628
|
-
description: el.getAttribute("data-description"),
|
|
731
|
+
let started_script
|
|
732
|
+
let loaded = {}
|
|
733
|
+
let cursorIndex = 0;
|
|
734
|
+
let interacted = false
|
|
735
|
+
document.addEventListener("click", (e) => {
|
|
736
|
+
interacted = true
|
|
629
737
|
})
|
|
630
|
-
|
|
631
|
-
const
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
738
|
+
const n = new N()
|
|
739
|
+
const getTarget = (href) => {
|
|
740
|
+
let u
|
|
741
|
+
if (href.startsWith("http")) {
|
|
742
|
+
return href
|
|
743
|
+
} else if (href.startsWith("/")) {
|
|
744
|
+
u = new URL("http://localhost" + href)
|
|
745
|
+
u.search = ""
|
|
746
|
+
return u.pathname
|
|
747
|
+
} else {
|
|
748
|
+
u = new URL("http://localhost/" + href)
|
|
749
|
+
u.search = ""
|
|
750
|
+
return u.pathname
|
|
640
751
|
}
|
|
641
752
|
}
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
753
|
+
const subUrlOf = (s, f) => {
|
|
754
|
+
|
|
755
|
+
let subsetUrl = (s.startsWith("http") ? s : "http://localhost" + s)
|
|
756
|
+
let fullUrl = (f.startsWith("http") ? f: "http://localhost" + f)
|
|
757
|
+
|
|
758
|
+
const subsetParsed = new URL(subsetUrl)
|
|
759
|
+
const fullParsed = new URL(fullUrl)
|
|
760
|
+
|
|
761
|
+
if (subsetParsed.pathname !== fullParsed.pathname) {
|
|
762
|
+
return false;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
// Check if all search parameters in the subset URL are present in the full URL
|
|
766
|
+
for (const [key, val] of subsetParsed.searchParams) {
|
|
767
|
+
|
|
768
|
+
if (!fullParsed.searchParams.has(key)) {
|
|
769
|
+
return false
|
|
770
|
+
}
|
|
771
|
+
if (fullParsed.searchParams.get(key) !== val) {
|
|
772
|
+
return false
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
return true;
|
|
777
|
+
}
|
|
778
|
+
const renderCursor = () => {
|
|
779
|
+
document.querySelectorAll(".selectable").forEach((el) => {
|
|
780
|
+
el.classList.remove("cursor")
|
|
781
|
+
})
|
|
782
|
+
const target = document.querySelector(".selectable[data-index='" + cursorIndex + "']")
|
|
783
|
+
target.classList.add("cursor")
|
|
784
|
+
}
|
|
785
|
+
const nav = (type) => {
|
|
786
|
+
let targetFrame = document.querySelector("iframe:not(.hidden)")
|
|
787
|
+
if (type === "back") {
|
|
788
|
+
// targetFrame.contentWindow.history.back()
|
|
789
|
+
targetFrame.contentWindow.postMessage({
|
|
790
|
+
action: "back"
|
|
791
|
+
}, "*")
|
|
792
|
+
} else if (type === "forward") {
|
|
793
|
+
// targetFrame.contentWindow.history.forward()
|
|
794
|
+
targetFrame.contentWindow.postMessage({
|
|
795
|
+
action: "forward"
|
|
796
|
+
}, "*")
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
|
|
800
|
+
|
|
801
|
+
// if (location.hash && location.hash.length > 0) {
|
|
802
|
+
//// let id = getTarget(location.hash.slice(1))
|
|
803
|
+
//// let target = document.querySelector("aside [target='" + id + "']")
|
|
804
|
+
// let id = location.hash.slice(1)
|
|
805
|
+
// let type = id[0]
|
|
806
|
+
// let index = id.slice(1)
|
|
807
|
+
// let target = document.querySelector(`aside .${type} [data-index='${index}']`)
|
|
808
|
+
// let targetFrame = document.querySelector(`iframe[name='${target.target}']`)
|
|
809
|
+
// console.log({ target, targetFrame })
|
|
810
|
+
// if (type === "back") {
|
|
811
|
+
// targetFrame.contentWindow.history.back()
|
|
812
|
+
// } else if (type === "forward") {
|
|
813
|
+
// targetFrame.contentWindow.history.forward()
|
|
814
|
+
// }
|
|
815
|
+
// /*
|
|
816
|
+
// targetFrame.contentWindow.postMessage({
|
|
817
|
+
// action: type
|
|
818
|
+
// }, "*")
|
|
819
|
+
// */
|
|
820
|
+
// }
|
|
821
|
+
}
|
|
822
|
+
const renderSelection = (e, force) => {
|
|
823
|
+
let init = document.querySelector("[data-init]")
|
|
824
|
+
if (init) {
|
|
825
|
+
location.href = init.href
|
|
826
|
+
return
|
|
827
|
+
}
|
|
828
|
+
if (location.hash && location.hash.length > 0) {
|
|
829
|
+
let target
|
|
830
|
+
if (location.hash && location.hash.length > 0) {
|
|
831
|
+
let id = location.hash.slice(1)
|
|
832
|
+
let selector
|
|
833
|
+
if (id.startsWith("@")) {
|
|
834
|
+
selector = `aside [target='${id}']`
|
|
835
|
+
} else {
|
|
836
|
+
let type = id[0]
|
|
837
|
+
let index = id.slice(1)
|
|
838
|
+
console.log({ type, index })
|
|
839
|
+
selector = `aside .${type} [data-index='${index}']`
|
|
840
|
+
}
|
|
841
|
+
if (e) {
|
|
842
|
+
// If the renderSelection is triggered by an event, look for the frame-link that's triggering the event
|
|
843
|
+
if (e.target.classList.contains("frame-link")) {
|
|
844
|
+
target = e.target
|
|
845
|
+
} else {
|
|
846
|
+
target = e.target.closest(".frame-link")
|
|
847
|
+
}
|
|
848
|
+
} else {
|
|
849
|
+
// if not triggered by an event, look for the target from the location hash
|
|
850
|
+
target = document.querySelector(selector)
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
|
|
855
|
+
// if the target was found either through:
|
|
856
|
+
// 1. looking for the frame-link that triggered the event
|
|
857
|
+
// 2. or by looking at the location hash
|
|
858
|
+
//
|
|
859
|
+
// => select that tab and frame
|
|
860
|
+
|
|
861
|
+
if (target) {
|
|
862
|
+
|
|
863
|
+
// display the menu button at the top
|
|
864
|
+
// maximize container
|
|
865
|
+
// minimize aside
|
|
866
|
+
|
|
867
|
+
document.querySelector(".container").classList.add("active")
|
|
868
|
+
document.querySelector("aside").classList.remove("active")
|
|
869
|
+
} else {
|
|
870
|
+
document.querySelector(".container").classList.remove("active")
|
|
871
|
+
document.querySelector("aside").classList.add("active")
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
if (target) {
|
|
875
|
+
|
|
876
|
+
|
|
877
|
+
// Instantiate a frame with the selected target's href
|
|
878
|
+
let url = target.href
|
|
879
|
+
|
|
880
|
+
if (!url) {
|
|
881
|
+
return
|
|
882
|
+
}
|
|
883
|
+
// document.querySelector("#open-browser").href = url
|
|
884
|
+
// document.querySelector("#clone-tab").setAttribute("data-href", url)
|
|
885
|
+
|
|
886
|
+
//document.querySelector("#location").value = url
|
|
887
|
+
|
|
888
|
+
if (target.pathname.startsWith("/run")) {
|
|
889
|
+
document.querySelector("#location").value = target.pathname.slice(4)
|
|
890
|
+
} else {
|
|
891
|
+
document.querySelector("#location").value = target.pathname
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
|
|
895
|
+
// select the selected target element (tab)
|
|
896
|
+
document.querySelectorAll(".frame-link").forEach((el) => {
|
|
897
|
+
el.classList.remove("selected")
|
|
898
|
+
})
|
|
899
|
+
target.classList.add("selected")
|
|
900
|
+
|
|
901
|
+
// hide all frames
|
|
902
|
+
document.querySelectorAll("iframe").forEach((el) => {
|
|
903
|
+
el.classList.add("hidden")
|
|
904
|
+
})
|
|
905
|
+
|
|
906
|
+
|
|
907
|
+
|
|
908
|
+
// Look for the frame
|
|
909
|
+
// 1. if it's hard (".h")
|
|
910
|
+
// look for the url that matches
|
|
911
|
+
// 2. if it's soft (".s")
|
|
912
|
+
// find using the name attribute
|
|
913
|
+
let targetFrame;
|
|
914
|
+
if (target.closest(".h")) {
|
|
915
|
+
let hardFrames = document.querySelectorAll(".browserview iframe[name^='@']")
|
|
916
|
+
let port = new URL(target.href).port || 80
|
|
917
|
+
for(let frame of hardFrames) {
|
|
918
|
+
console.log({ src: frame.src, href: target.href, target: target.target })
|
|
919
|
+
// Types of links in the tab
|
|
920
|
+
let targetPath = new URL(target.href).pathname
|
|
921
|
+
let framePath = new URL(frame.src).pathname
|
|
922
|
+
if (targetPath === framePath) {
|
|
923
|
+
let beforeName = frame.name
|
|
924
|
+
frame.name = target.target
|
|
925
|
+
console.log("SET FRAME", { before: beforeName, after: frame.name, target: target.target })
|
|
926
|
+
targetFrame = frame
|
|
927
|
+
break
|
|
928
|
+
}
|
|
929
|
+
// find the frame whose path matches
|
|
930
|
+
}
|
|
931
|
+
} else if (target.closest(".s")) {
|
|
932
|
+
targetFrame = document.querySelector(`iframe[name='${target.target}']`)
|
|
933
|
+
} else if (target.closest(".n")) {
|
|
934
|
+
targetFrame = document.querySelector(`iframe[name='${target.target}']`)
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
/*
|
|
938
|
+
// Load the link in the frame
|
|
939
|
+
|
|
940
|
+
1. if the frame was found:
|
|
941
|
+
- if "refresh": true => refresh
|
|
942
|
+
- otherwise,
|
|
943
|
+
- if the target frame has been already loaded, don't do anything
|
|
944
|
+
- frame: start.json?mode=abc, link: start.json?mode=abc => don't touch
|
|
945
|
+
- link === frame
|
|
946
|
+
- frame: start.json?mode=abc, link: start.json?mode=def => should load
|
|
947
|
+
- link !== frame && !frame.includes(link)
|
|
948
|
+
- frame: start.json?mode=abc, link: start.json => don't touch
|
|
949
|
+
- link !== frame && frame.includes(link)
|
|
950
|
+
|
|
951
|
+
|
|
952
|
+
|
|
953
|
+
if the link is different
|
|
954
|
+
|
|
955
|
+
- if the target frame has not been loaded, refresh
|
|
956
|
+
2. if the frame was NOT found => create one
|
|
957
|
+
|
|
958
|
+
*/
|
|
959
|
+
|
|
960
|
+
if (targetFrame) {
|
|
961
|
+
targetFrame.classList.remove("hidden")
|
|
962
|
+
let mode = target.getAttribute("data-mode")
|
|
963
|
+
if (mode === "refresh") {
|
|
964
|
+
targetFrame.src = target.href
|
|
965
|
+
} else {
|
|
966
|
+
if (e) {
|
|
967
|
+
if (target.closest(".h")) {
|
|
968
|
+
e.preventDefault()
|
|
969
|
+
e.stopPropagation()
|
|
970
|
+
let sub = subUrlOf(target.href, targetFrame.src)
|
|
971
|
+
if (!sub) {
|
|
972
|
+
targetFrame.src = target.href
|
|
973
|
+
}
|
|
974
|
+
//if (target.href === targetFrame.src) {
|
|
975
|
+
// // same url. don't do anything
|
|
976
|
+
// e.preventDefault()
|
|
977
|
+
// e.stopPropagation()
|
|
978
|
+
//} else {
|
|
979
|
+
// if (targetFrame.src.includes(target.href)) {
|
|
980
|
+
// // different url, but the frame's url contains the tab url => don't touch
|
|
981
|
+
// e.preventDefault()
|
|
982
|
+
// e.stopPropagation()
|
|
983
|
+
// } else {
|
|
984
|
+
// // different url, and the frame's url does not contain the tab url => change the src of the frame and load
|
|
985
|
+
// targetFrame.src = target.href
|
|
986
|
+
// e.preventDefault()
|
|
987
|
+
// e.stopPropagation()
|
|
988
|
+
// }
|
|
989
|
+
//}
|
|
990
|
+
} else if (target.closest(".s")) {
|
|
991
|
+
// load unconditionally => .s doesn't change
|
|
992
|
+
e.preventDefault()
|
|
993
|
+
e.stopPropagation()
|
|
994
|
+
} else if (target.closest(".n")) {
|
|
995
|
+
// load unconditionally => .n doesn't change
|
|
996
|
+
e.preventDefault()
|
|
997
|
+
e.stopPropagation()
|
|
998
|
+
}
|
|
999
|
+
} else {
|
|
1000
|
+
if (force) {
|
|
1001
|
+
targetFrame.src = target.href
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
targetFrame.contentWindow.postMessage({
|
|
1005
|
+
action: "foreground"
|
|
1006
|
+
}, "*")
|
|
1007
|
+
}
|
|
1008
|
+
} else {
|
|
1009
|
+
let frame = document.createElement("iframe")
|
|
1010
|
+
frame.name = target.target
|
|
1011
|
+
frame.src = target.href
|
|
1012
|
+
frame.setAttribute(
|
|
1013
|
+
"allow",
|
|
1014
|
+
"clipboard-read *; clipboard-write *; accelerometer *; ambient-light-sensor *; autoplay *; battery *; camera *; display-capture *; gamepad *; geolocation *; gyroscope *; hid *; identity-credentials-get *; microphone *; midi *; otp-credentials *; serial *;"
|
|
1015
|
+
)
|
|
1016
|
+
document.querySelector("main").appendChild(frame)
|
|
1017
|
+
loaded[target.target] = true
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
// if (targetFrame) {
|
|
1021
|
+
// targetFrame.classList.remove("hidden")
|
|
1022
|
+
//
|
|
1023
|
+
// // if the iframe already exists, do not
|
|
1024
|
+
// if (loaded[target.target]){
|
|
1025
|
+
//
|
|
1026
|
+
// // Force refresh option
|
|
1027
|
+
// //
|
|
1028
|
+
// // menu := [{
|
|
1029
|
+
// // text,
|
|
1030
|
+
// // icon,
|
|
1031
|
+
// // mode: "refresh" => refresh regardless of any condition
|
|
1032
|
+
// // }]
|
|
1033
|
+
// let mode = target.getAttribute("data-mode")
|
|
1034
|
+
// if (mode === "refresh") {
|
|
1035
|
+
// targetFrame.src = target.href
|
|
1036
|
+
// } else {
|
|
1037
|
+
// console.log("# 4")
|
|
1038
|
+
// if (e) {
|
|
1039
|
+
// // if triggered by a click event,
|
|
1040
|
+
// // 1. if it's a hard link (".h")
|
|
1041
|
+
// // - ignore if the pathname is the same
|
|
1042
|
+
// // - reload if
|
|
1043
|
+
// console.log("# 5", { src: targetFrame.src, href: target.href, target: target.target })
|
|
1044
|
+
// // triggered with a click
|
|
1045
|
+
// // do not reload iframe if the href and the src is the same
|
|
1046
|
+
// if (target.closest(".h")) {
|
|
1047
|
+
// // if (targetFrame.src.includes(target.target)) {
|
|
1048
|
+
// if (targetFrame.src.includes(target.href)) {
|
|
1049
|
+
// // if (targetFrame.src === target.href) {
|
|
1050
|
+
// e.preventDefault()
|
|
1051
|
+
// e.stopPropagation()
|
|
1052
|
+
// }
|
|
1053
|
+
// } else if (target.closest(".s")) {
|
|
1054
|
+
// e.preventDefault()
|
|
1055
|
+
// e.stopPropagation()
|
|
1056
|
+
// }
|
|
1057
|
+
// } else {
|
|
1058
|
+
// // if not triggered by event
|
|
1059
|
+
// // refresh ONLY if programmatically forced refresh
|
|
1060
|
+
// console.log("# 6")
|
|
1061
|
+
// if (force) {
|
|
1062
|
+
// console.log("# 7")
|
|
1063
|
+
// targetFrame.src = target.href
|
|
1064
|
+
// }
|
|
1065
|
+
// }
|
|
1066
|
+
// }
|
|
1067
|
+
//
|
|
1068
|
+
// } else {
|
|
1069
|
+
// console.log("# 8")
|
|
1070
|
+
// //targetFrame.contentWindow.addEventListener("load", () => {
|
|
1071
|
+
// if (e) {
|
|
1072
|
+
// console.log("# 9")
|
|
1073
|
+
// // coming from a click => don't need to set the src
|
|
1074
|
+
// } else {
|
|
1075
|
+
// console.log("# 10")
|
|
1076
|
+
// // load without click
|
|
1077
|
+
// if (targetFrame.src !== target.href) {
|
|
1078
|
+
// console.log("# 11")
|
|
1079
|
+
// targetFrame.src = target.href
|
|
1080
|
+
// }
|
|
1081
|
+
// }
|
|
1082
|
+
// loaded[target.target] = true
|
|
1083
|
+
// //});
|
|
1084
|
+
// }
|
|
1085
|
+
// } else {
|
|
1086
|
+
// console.log("# 12")
|
|
1087
|
+
// let frame = document.createElement("iframe")
|
|
1088
|
+
// frame.name = target.target
|
|
1089
|
+
// frame.src = target.href
|
|
1090
|
+
// frame.setAttribute(
|
|
1091
|
+
// "allow",
|
|
1092
|
+
// "clipboard-read *; clipboard-write *; accelerometer *; ambient-light-sensor *; autoplay *; battery *; camera *; display-capture *; gamepad *; geolocation *; gyroscope *; hid *; identity-credentials-get *; microphone *; midi *; otp-credentials *; serial *;"
|
|
1093
|
+
// )
|
|
1094
|
+
// document.querySelector("main").appendChild(frame)
|
|
1095
|
+
// loaded[target.target] = true
|
|
1096
|
+
// }
|
|
1097
|
+
} else {
|
|
1098
|
+
console.log("# 13")
|
|
1099
|
+
// couldn't find item,
|
|
1100
|
+
// clear the hash
|
|
1101
|
+
//
|
|
1102
|
+
location.hash = ""
|
|
1103
|
+
}
|
|
1104
|
+
} else {
|
|
1105
|
+
console.log("# 14")
|
|
1106
|
+
document.querySelector(".container").classList.remove("active")
|
|
1107
|
+
document.querySelector("aside").classList.add("active")
|
|
1108
|
+
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
renderSelection()
|
|
1112
|
+
|
|
1113
|
+
|
|
1114
|
+
if (document.querySelector("#menu")) {
|
|
1115
|
+
document.querySelector("#menu").addEventListener("click", async (e) => {
|
|
1116
|
+
document.querySelector("aside").classList.toggle("hidden")
|
|
1117
|
+
document.querySelector("#menu").classList.toggle("margin")
|
|
1118
|
+
})
|
|
1119
|
+
}
|
|
1120
|
+
document.querySelector("aside").addEventListener("click", async (e) => {
|
|
1121
|
+
let target
|
|
1122
|
+
|
|
1123
|
+
// 0. handle dropdowns
|
|
1124
|
+
if (e.target.classList.contains("revealer")) {
|
|
1125
|
+
target = e.target
|
|
1126
|
+
} else {
|
|
1127
|
+
target = e.target.closest(".revealer")
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1130
|
+
if (target) {
|
|
1131
|
+
e.preventDefault()
|
|
1132
|
+
e.stopPropagation()
|
|
1133
|
+
let group = target.getAttribute("data-group")
|
|
1134
|
+
document.querySelector(group).classList.toggle("hidden")
|
|
1135
|
+
target.querySelector(".loader .fa-angle-down").classList.toggle("hidden")
|
|
1136
|
+
target.querySelector(".loader .fa-angle-up").classList.toggle("hidden")
|
|
1137
|
+
return
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
|
|
1141
|
+
|
|
1142
|
+
// 1. handle delete
|
|
1143
|
+
if (e.target.classList.contains("del")) {
|
|
1144
|
+
target = e.target
|
|
1145
|
+
} else {
|
|
1146
|
+
target = e.target.closest(".del")
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
if (target) {
|
|
1150
|
+
e.preventDefault()
|
|
1151
|
+
e.stopPropagation()
|
|
1152
|
+
// Delete
|
|
1153
|
+
// delete link
|
|
1154
|
+
let el = target.closest(".frame-link")
|
|
1155
|
+
console.log("target", el.target)
|
|
1156
|
+
let iframe = document.querySelector("iframe[name='" + el.target + "']")
|
|
1157
|
+
console.log("iframe", iframe)
|
|
1158
|
+
if (iframe) {
|
|
1159
|
+
// delete iframe
|
|
1160
|
+
iframe.remove()
|
|
1161
|
+
}
|
|
1162
|
+
el.remove()
|
|
1163
|
+
// update tabs
|
|
1164
|
+
await syncTabs()
|
|
1165
|
+
return
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
|
|
1169
|
+
// 2. handle shudown
|
|
1170
|
+
if (e.target.classList.contains("shutdown")) {
|
|
1171
|
+
target = e.target
|
|
1172
|
+
} else {
|
|
1173
|
+
target = e.target.closest(".shutdown")
|
|
1174
|
+
}
|
|
1175
|
+
if (target) {
|
|
1176
|
+
e.preventDefault()
|
|
1177
|
+
e.stopPropagation()
|
|
1178
|
+
let link = target.closest("[href]")
|
|
1179
|
+
let src = new URL(link.href).pathname
|
|
1180
|
+
target.querySelector("i.fa-square").className = "fa-solid fa-check"
|
|
1181
|
+
n.Noty({
|
|
1182
|
+
text: `stopping ${src}`,
|
|
1183
|
+
silent: true,
|
|
1184
|
+
timeout: 2000
|
|
1185
|
+
})
|
|
1186
|
+
console.log("src", src)
|
|
1187
|
+
|
|
1188
|
+
let socket = new Socket()
|
|
1189
|
+
socket.run({
|
|
1190
|
+
method: "kernel.api.stop",
|
|
1191
|
+
params: {
|
|
1192
|
+
uri: "~" + src
|
|
1193
|
+
}
|
|
1194
|
+
}, (packet) => {
|
|
1195
|
+
if (packet.type === "result") {
|
|
1196
|
+
socket.close()
|
|
1197
|
+
n.Noty({
|
|
1198
|
+
timeout: 2000,
|
|
1199
|
+
text: `stopped`,
|
|
1200
|
+
silent: true
|
|
1201
|
+
})
|
|
1202
|
+
console.log("Refresh 4")
|
|
1203
|
+
}
|
|
1204
|
+
})
|
|
1205
|
+
|
|
1206
|
+
return
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
|
|
1210
|
+
|
|
1211
|
+
// 3. handle select
|
|
1212
|
+
if (e.target.classList.contains("frame-link")) {
|
|
1213
|
+
target = e.target
|
|
1214
|
+
} else {
|
|
1215
|
+
target = e.target.closest(".frame-link")
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
|
|
1219
|
+
|
|
1220
|
+
if (target) {
|
|
1221
|
+
|
|
1222
|
+
// if data-confirm exists, ask for confirmation
|
|
1223
|
+
// if not, then just go forward
|
|
1224
|
+
let confirmText = target.getAttribute("data-confirm")
|
|
1225
|
+
if (confirmText && confirmText.length > 0) {
|
|
1226
|
+
const confirmed = confirm(confirmText)
|
|
1227
|
+
if (!confirmed) {
|
|
1228
|
+
e.preventDefault()
|
|
1229
|
+
e.stopPropagation()
|
|
1230
|
+
return
|
|
1231
|
+
}
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
if (target.getAttribute("data-action")) {
|
|
1235
|
+
let actionStr = target.getAttribute("data-action")
|
|
1236
|
+
let action = JSON.parse(actionStr)
|
|
1237
|
+
console.log("action", action)
|
|
1238
|
+
if (action.method === "stop" && action.uri) {
|
|
1239
|
+
let socket = new Socket()
|
|
1240
|
+
socket.run({
|
|
1241
|
+
method: "kernel.api.stop",
|
|
1242
|
+
params: {
|
|
1243
|
+
uri: action.uri//"~" + location.pathname
|
|
1244
|
+
}
|
|
1245
|
+
}, (packet) => {
|
|
1246
|
+
if (packet.type === "result") {
|
|
1247
|
+
socket.close()
|
|
1248
|
+
// location.href = location.href
|
|
1249
|
+
}
|
|
1250
|
+
})
|
|
1251
|
+
}
|
|
1252
|
+
} else if (target.getAttribute("data-filepath")) {
|
|
1253
|
+
return
|
|
1254
|
+
} else if (target.target === "_blank") {
|
|
1255
|
+
// nothing
|
|
1256
|
+
} else {
|
|
1257
|
+
if (target.classList.contains("reveal")) {
|
|
1258
|
+
// nested menu
|
|
1259
|
+
target.closest(".nested-menu").querySelector(".submenu").classList.toggle("hidden")
|
|
1260
|
+
target.querySelector(".loader .fa-angle-down").classList.toggle("hidden")
|
|
1261
|
+
target.querySelector(".loader .fa-angle-up").classList.toggle("hidden")
|
|
1262
|
+
e.preventDefault()
|
|
1263
|
+
e.stopPropagation()
|
|
1264
|
+
} else {
|
|
1265
|
+
//location.hash = target.target
|
|
1266
|
+
|
|
1267
|
+
|
|
1268
|
+
// let id = getTarget(target.getAttribute("href"))
|
|
1269
|
+
// console.log("ID", id, target.href)
|
|
1270
|
+
// location.hash = id
|
|
1271
|
+
|
|
1272
|
+
//location.hash = target.getAttribute("href")
|
|
1273
|
+
|
|
1274
|
+
if (target.closest(".h")) {
|
|
1275
|
+
if (target.target) {
|
|
1276
|
+
location.hash = target.target
|
|
1277
|
+
}
|
|
1278
|
+
} else {
|
|
1279
|
+
let index = target.getAttribute("data-index")
|
|
1280
|
+
let type = target.closest(".m").getAttribute("data-type")
|
|
1281
|
+
|
|
1282
|
+
|
|
1283
|
+
if (type) {
|
|
1284
|
+
location.hash = type + index
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
document.querySelectorAll(".frame-link").forEach((el) => {
|
|
1289
|
+
el.classList.remove("selected")
|
|
1290
|
+
})
|
|
1291
|
+
target.classList.add("selected")
|
|
1292
|
+
|
|
1293
|
+
renderSelection(e)
|
|
1294
|
+
}
|
|
1295
|
+
}
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
|
|
1299
|
+
|
|
1300
|
+
})
|
|
1301
|
+
</script>
|
|
645
1302
|
</body>
|
|
646
1303
|
</html>
|