pinokiod 3.19.2 → 3.19.4

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.
@@ -0,0 +1,1542 @@
1
+ <html>
2
+ <head>
3
+ <meta charset="UTF-8">
4
+ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
5
+ <link href="/css/fontawesome.min.css" rel="stylesheet">
6
+ <link href="/css/solid.min.css" rel="stylesheet">
7
+ <link href="/css/regular.min.css" rel="stylesheet">
8
+ <link href="/css/brands.min.css" rel="stylesheet">
9
+ <link href="/markdown.css" rel="stylesheet"/>
10
+ <link href="/noty.css" rel="stylesheet"/>
11
+ <link href="/filepond.min.css" rel="stylesheet" />
12
+ <link href="/filepond-plugin-image-preview.min.css" rel="stylesheet" />
13
+ <link href="/filepond-plugin-image-edit.min.css" rel="stylesheet" />
14
+ <link href="/style.css" rel="stylesheet"/>
15
+ <% if (agent === "electron") { %>
16
+ <link href="/electron.css" rel="stylesheet"/>
17
+ <% } %>
18
+ <style>
19
+ .online {
20
+ width: 10px;
21
+ height: 10px;
22
+ background: yellowgreen;
23
+ border-radius: 10px;
24
+ }
25
+ #menu {
26
+ display: flex;
27
+ }
28
+ #menu i {
29
+ display: block;
30
+ }
31
+ #menu img {
32
+ display: none;
33
+ height: 30px;
34
+ object-fit: contain;
35
+ /*
36
+ border-radius: 20px
37
+ */
38
+ }
39
+ #menu.margin {
40
+ /*
41
+ padding: 5px;
42
+ */
43
+ }
44
+ #menu.margin i {
45
+ display: none;
46
+ }
47
+ #menu.margin img {
48
+ display: block;
49
+ }
50
+ html, body {
51
+ width: 100%;
52
+ height: 100%;
53
+ margin: 0;
54
+ }
55
+ body {
56
+ display: flex;
57
+ flex-direction: column;
58
+ }
59
+ .menu {
60
+ overflow: auto;
61
+ }
62
+ body.dark .m {
63
+ border-top: 1px solid rgba(255,255,255,0.04);
64
+ }
65
+ .m {
66
+ border-top: 1px solid rgba(0,0,0,0.04);
67
+ }
68
+ .container {
69
+ position: relative;
70
+ display: flex;
71
+ flex-direction: column;
72
+ flex-grow: 1;
73
+ }
74
+ body aside {
75
+ /*
76
+ background: var(--light-bg);
77
+ */
78
+ border-right: 1px solid rgba(0,0,0,0.04);
79
+ height: 100%;
80
+ padding-bottom: 100px;
81
+ box-sizing: border-box;
82
+ }
83
+ body.dark aside {
84
+ background: var(--dark-bg);
85
+ border-right: 1px solid rgba(255,255,255,0.04);
86
+ }
87
+ aside {
88
+ /*
89
+ display: flex;
90
+ flex-direction: column;
91
+ */
92
+ width: 200px;
93
+ overflow: auto;
94
+ box-sizing: border-box;
95
+ flex-shrink: 0;
96
+ }
97
+ main {
98
+ flex-grow: 1;
99
+ min-height: 0;
100
+ /*
101
+ height: 100%;
102
+ */
103
+ }
104
+ main iframe[name^=http] {
105
+ background: white;
106
+ }
107
+ main iframe {
108
+ width: 100%;
109
+ height: 100%;
110
+ border: none;
111
+ }
112
+ /*
113
+ .header-item.indent {
114
+ padding-left: 23px !important;
115
+ }
116
+ */
117
+ .header-item {
118
+ /*
119
+ display: block;
120
+ */
121
+ display: flex;
122
+ font-size: 12px;
123
+ text-decoration: none;
124
+ align-items: center;
125
+ border-radius: 0;
126
+ cursor: pointer;
127
+ }
128
+ .header-item.selected {
129
+ }
130
+ .header-item .btn2 {
131
+ margin: 0;
132
+ border: none;
133
+ /*
134
+ color: var(--light-color);
135
+ */
136
+ }
137
+ body.dark .header-item .btn2 {
138
+ /*
139
+ color: var(--darkt-color);
140
+ */
141
+ }
142
+ .bar .btn2 i {
143
+ display: block;
144
+ margin-right: 5px;
145
+ }
146
+ .header-item > * {
147
+ display: block;
148
+ }
149
+ .header-item img {
150
+ /*
151
+ width: 60px;
152
+ */
153
+ height: 80px;
154
+ width: 80px;
155
+ /*
156
+ border-radius: 10px;
157
+ */
158
+ object-fit: contain;
159
+ display: inline-block;
160
+ /*
161
+ border-radius: 30px;
162
+ */
163
+ }
164
+ body.dark .header-item.btn {
165
+ /*
166
+ color: white;
167
+ */
168
+ color: var(--dark-color);
169
+ }
170
+ .header-item.btn {
171
+ padding: 8px;
172
+ background: none !important;
173
+ color: var(--light-color);
174
+ }
175
+ .logo {
176
+ font-size: 20px;
177
+ padding: 20px;
178
+ }
179
+ body .logo {
180
+ color: var(--light-color);
181
+ }
182
+ body.dark .logo {
183
+ color: var(--dark-btn-color);
184
+ /*
185
+ color: white;
186
+ */
187
+ }
188
+ body #new-window {
189
+ color: var(--light-color);
190
+ }
191
+ body.dark #new-window {
192
+ color: var(--dark-btn-color);
193
+ /*
194
+ color: white;
195
+ */
196
+ }
197
+ /*
198
+ .dark .app-info {
199
+ background: rgba(255,255,255,0.04);
200
+ }
201
+ */
202
+ .app-info-card img {
203
+ padding: 10px;
204
+ }
205
+ .app-info {
206
+
207
+ /*
208
+ display: flex;
209
+ */
210
+ box-sizing: border-box;
211
+ text-align: center;;
212
+ font-weight: bold;
213
+ align-items: center;
214
+ /*
215
+ background: rgba(0,0,0,0.04);
216
+ */
217
+ }
218
+ .folderbuttons {
219
+ display: grid;
220
+ grid-template-columns: repeat(4, 1fr);
221
+ gap: 0px;
222
+ }
223
+ .header-btns {
224
+ padding: 0 !important;
225
+ }
226
+ body.dark .header-btns {
227
+ border-top: 1px solid rgba(255,255,255,0.04);
228
+ }
229
+ .app-info-edit {
230
+ text-decoration: none;
231
+ color: black;
232
+ border-bottom: 1px solid rgba(255,255,255,0.1);
233
+ }
234
+ /*
235
+ .dark .app-info-edit {
236
+ border-top: 1px solid rgba(255,255,255,0.2);
237
+ border-bottom: 1px solid rgba(255,255,255,0.2);
238
+ }
239
+ */
240
+ .dark .app-info-edit:hover {
241
+ background: rgba(0,0,0,0.2);
242
+ }
243
+ .app-info-edit:hover{
244
+ background: rgba(0,0,0,0.05);
245
+ }
246
+ .app-info-edit i{
247
+ display: block;
248
+ }
249
+ .app-info-edit, .app-info-copy {
250
+ font-weight: normal;
251
+
252
+ /*
253
+ border-radius: 20px;
254
+ */
255
+ font-size: 12px;
256
+ padding: 15px 5px;
257
+ /*
258
+ margin: 10px 20px 0;
259
+ */
260
+ }
261
+ .app-info-card {
262
+ /*
263
+ padding: 10px !important;
264
+ */
265
+ display: flex;
266
+ }
267
+ .app-info .btn {
268
+ width: 100%;
269
+ box-sizing: border-box;
270
+ }
271
+ body.dark .app-info .mode-section {
272
+ background: rgba(0,0,0,0.4);
273
+ }
274
+ .app-info .mode-section {
275
+ background: rgba(0,0,0,0.06);
276
+ padding: 20px;
277
+ box-sizing: border-box;
278
+ width: 100%;
279
+ text-align: left;
280
+ }
281
+ .app-info .mode-section .desc {
282
+ font-weight: normal;
283
+ opacity: 0.7;
284
+ }
285
+ .app-info .mode-section h3 {
286
+ font-size: 18px;
287
+ line-height: 26px;
288
+ margin: 0;
289
+ }
290
+ body.dark .app-info .mode-section .btn {
291
+ border: 1px solid rgba(255,255,255,0.1);
292
+ }
293
+ .app-info .mode-section .btn {
294
+ margin-top: 10px;
295
+ text-align: center;
296
+ }
297
+ .app-info-card > * {
298
+ /*
299
+ padding: 5px;
300
+ */
301
+ color: var(--light-color);
302
+ text-decoration: none;
303
+ box-sizing: border-box;
304
+ }
305
+ body.dark .app-info-card > * {
306
+ color: var(--dark-color);
307
+ }
308
+ .app-info-title {
309
+ padding: 15px 0;
310
+ }
311
+ .footer {
312
+ /*
313
+ display: flex;
314
+ */
315
+ display: grid;
316
+ grid-template-columns: repeat(4, 1fr);
317
+ }
318
+ .footer > * {
319
+ padding: 10px !important;
320
+ display: block;
321
+ box-sizing: border-box;
322
+ font-size: 12px !important;
323
+ text-align: center;
324
+ }
325
+ .footer i {
326
+ margin: 0 !important;
327
+ padding: 5px;
328
+ }
329
+ .footer a {
330
+ font-size: 14px;
331
+ }
332
+ body .footer {
333
+ border-bottom: 1px solid rgba(0,0,0,0.04);
334
+ }
335
+ body.dark .footer {
336
+ border-bottom: 1px solid rgba(255,255,255,0.04);
337
+ }
338
+ body.dark .header-item.cursor {
339
+ background: rgba(0,0,0, 0.2) !important;
340
+ }
341
+ .header-item.cursor {
342
+ background: rgba(0,0,100, 0.03) !important;
343
+ /*
344
+ border-left: 5px solid gold;
345
+ */
346
+ }
347
+ .frame-link {
348
+ cursor: pointer;
349
+ }
350
+ body .frame-link.selected {
351
+ /*
352
+ border-right: 10px solid gold;
353
+ */
354
+ background: black !important;
355
+ color: white;
356
+ /*
357
+ background: rgba(0,0,100,0.06) !important;
358
+ */
359
+ }
360
+ .frame-link.selected .del {
361
+ color: white;
362
+ }
363
+ body.dark .frame-link.selected {
364
+ background: rgba(0,0,0,0.7) !important;
365
+ }
366
+ .frame-link .loader {
367
+ /*
368
+ padding: 5px;
369
+ */
370
+ }
371
+ .loader {
372
+ flex-shrink: 0;
373
+ }
374
+ .loader .btn:hover {
375
+ color: royalblue;
376
+ border-color: royalblue;
377
+ }
378
+ .loader .btn {
379
+ padding: 4px 8px;
380
+ /*
381
+ border: 1px solid rgba(255,255,255,0.3);
382
+ */
383
+ }
384
+ .frame-link .tab {
385
+ flex-grow: 1;
386
+ /*
387
+ width: 100%;
388
+ */
389
+ word-break: break-word;
390
+ padding-right: 10px;
391
+ /*
392
+ margin-right: 10px;
393
+ */
394
+ }
395
+ .frame-link .tab .flexible {
396
+ min-width: 5px;
397
+ }
398
+ .frame-link .tab .display {
399
+ word-break: break-word;
400
+ }
401
+ body.dark .grid-btns {
402
+ border-top: 1px solid rgba(255,255,255,0.04);
403
+ border-bottom: 1px solid rgba(255,255,255,0.04);
404
+ }
405
+ .grid-btns {
406
+ border-top: 1px solid rgba(0,0,0,0.04);
407
+ border-bottom: 1px solid rgba(0,0,0,0.04);
408
+ display: grid;
409
+ grid-template-columns: repeat(2, 1fr);
410
+ grid-template-rows: repeat(2, 1fr);
411
+ /*
412
+ grid-template-columns: repeat(3, 1fr);
413
+ grid-template-rows: repeat(1, 1fr);
414
+ */
415
+ box-sizing: border-box;
416
+ }
417
+ .grid-btns .btn2 {
418
+ padding: 10px 10px;
419
+ color: var(--light-color);
420
+ border-radius: 0;
421
+ cursor: pointer;
422
+ font-size: 11px;
423
+ }
424
+ body.dark .grid-btns .btn2 {
425
+ /*
426
+ color: white;
427
+ */
428
+ color: var(--dark-btn-color);
429
+ }
430
+ .footer {
431
+ width: 100%;
432
+ }
433
+ .tab {
434
+ flex-grow: 1;
435
+ display: flex;
436
+ align-items: center;
437
+ padding-right: 10px;
438
+ }
439
+ .label i {
440
+ margin-right: 10px;
441
+ }
442
+ .tab i {
443
+ margin-right: 10px;
444
+ font-size: 12px;
445
+ width: 12px;
446
+ }
447
+ .menu-item-image {
448
+ width: 16px !important;
449
+ height: 16px !important;
450
+ margin-right: 10px;
451
+ background: white;
452
+ }
453
+ .temp-menu {
454
+ /*
455
+ border-top: 1px solid rgba(0,0,0,0.1);
456
+ */
457
+ }
458
+ .temp-menu .del i {
459
+ margin: 0;
460
+ }
461
+ #delete {
462
+ color: brown;
463
+ }
464
+ body .footer {
465
+ }
466
+ body.dark nav {
467
+ /*
468
+ border-bottom: 1px solid rgba(255,255,255,0.04);
469
+ */
470
+ border-top: 1px solid rgba(255,255,255,0.04);
471
+ }
472
+ /*
473
+ .container:hover nav {
474
+ display: block;
475
+ }
476
+ */
477
+ nav {
478
+ /*
479
+ overflow: hidden;
480
+ max-height: 0;
481
+ transition: max-height 0.4s ease-out;
482
+ display: none;
483
+ */
484
+
485
+ background: white;
486
+ /*
487
+ position: absolute;
488
+ bottom: 0;
489
+ left: 0;
490
+ right: 0;
491
+ */
492
+ /*
493
+ padding: 5px;
494
+ */
495
+ padding: 0;
496
+ cursor: grab !important;
497
+ -webkit-app-region: drag !important;
498
+ /*
499
+ border-bottom: 1px solid rgba(0,0,0,0.04);
500
+ */
501
+ border-top: 1px solid rgba(0,0,0,0.04);
502
+ box-sizing: border-box;
503
+ }
504
+ body.dark nav .btn2 {
505
+ border-right: 1px solid rgba(255,255,255,0.04);
506
+ }
507
+ nav .btn2 {
508
+ padding: 15px;
509
+ font-size: 12px;
510
+ /*
511
+ width: 70px;
512
+ */
513
+ box-sizing: border-box;
514
+ border-right: 1px solid rgba(0,0,0,0.04);
515
+ border-radius: 0;
516
+ text-transform: lowercase;
517
+ flex-shrink: 0;
518
+
519
+ display: flex;
520
+ /*
521
+ flex-direction: column;
522
+ */
523
+ justify-content: center;
524
+ align-items: center;
525
+ }
526
+ nav .logo {
527
+ font-size: 14px;
528
+ padding: 10px;
529
+ }
530
+ .error-message .btn i {
531
+ margin-right: 10px;
532
+ }
533
+ .error-message .btn {
534
+ margin-top: 20px;
535
+ align-items: center;
536
+ display: flex;
537
+ letter-spacing: 0px;
538
+ background: black;
539
+ color: yellow;
540
+ font-size: 20px;
541
+ padding: 10px 30px;
542
+ }
543
+ .error-message {
544
+ display: flex;
545
+ flex-direction: column;
546
+ justify-content: center;
547
+ align-items: center;
548
+ font-weight: bold;
549
+ background: yellow !important;
550
+ flex-grow: 1;
551
+ padding: 0 50px;
552
+ font-size: 40px;
553
+ line-height: 40px;
554
+ color: black;
555
+ letter-spacing: -2px;
556
+ }
557
+ body.dark #location {
558
+ color: white;
559
+ background: rgba(255,255,255,0.03);
560
+ }
561
+ #location {
562
+ background: rgba(0,0,0,0.04);
563
+ padding: 10px;
564
+ margin: 0 0 0 10px;
565
+ font-size: 12px;
566
+ font-family: verdana;
567
+ box-sizing: border-box;
568
+ flex-grow: 1;
569
+ border: none;
570
+ outline: none;
571
+ }
572
+ body.dark #open-location {
573
+ background: rgba(255,255,255,0.03);
574
+ color: white;
575
+ }
576
+ #open-location {
577
+ border: none;
578
+ color: black;
579
+ background: rgba(0,0,0,0.04);
580
+ padding: 10px;
581
+ margin-right: 10px;
582
+ font-size: 14px;
583
+ }
584
+ .bar {
585
+ -webkit-app-region: no-drag !important;
586
+ cursor: auto;
587
+ display: flex;
588
+ align-items: stretch;
589
+ width: 100%;
590
+ flex-wrap: wrap;
591
+ }
592
+ body.dark .header-item.cursor.header-top {
593
+ background: none !important;
594
+ }
595
+ .header-item.cursor.header-top {
596
+ background: none !important;
597
+ }
598
+ .header-item.header-top {
599
+ display: block;
600
+ }
601
+ #new-tab:hover {
602
+ background: rgba(0,0,0,0.06) !important;
603
+ color: rgb(200,0,0) !important;
604
+ }
605
+
606
+ #new-tab {
607
+ cursor: pointer !important;
608
+ justify-content: center;
609
+ /*
610
+ border-top: 1px solid rgba(0,0,0,0.04);
611
+ */
612
+ }
613
+
614
+ body.dark #new-tab {
615
+ /*
616
+ border-top: 1px solid rgba(255,255,255,0.04);
617
+ */
618
+ }
619
+ body.dark .submenu {
620
+ border-left: 1px solid rgba(255,255,255,0.3);
621
+ }
622
+ .submenu {
623
+ border-left: 1px solid black;
624
+ margin-left: 15px;
625
+ box-sizing: border-box;
626
+ }
627
+ #menu-mobile {
628
+ display: none;
629
+ }
630
+ .tabmenu .label {
631
+ padding: 10px;
632
+ border-bottom: 1px solid rgba(255,255,255,0.04);
633
+ text-transform: uppercase;
634
+ font-size: 12px;
635
+ font-weight: bold;
636
+ }
637
+ .disk-usage {
638
+ flex-grow: 1;
639
+ text-align: right;
640
+ font-weight: bold;
641
+ }
642
+ .disk-usage i {
643
+ margin-right: 5px;
644
+ font-size: 16px !important;
645
+ }
646
+
647
+
648
+ .custom-label {
649
+ position: absolute;
650
+ top: 0;
651
+ left: 0;
652
+ right: 0;
653
+ bottom: 0;
654
+ display: flex;
655
+ align-items: center;
656
+ justify-content: center;
657
+ pointer-events: none; /* Let clicks fall through to FilePond */
658
+ font-size: 14px;
659
+ color: rgba(0, 0, 0, 0.5);
660
+ z-index: 5;
661
+ }
662
+ .appcanvas {
663
+ overflow: auto;
664
+ display: flex;
665
+ flex-grow: 1;
666
+ border-top: 1px solid rgba(0, 0,0 ,0.04);
667
+ }
668
+ body.dark .appcanvas {
669
+ border-top: 1px solid rgba(255,255,255,0.04);
670
+ }
671
+ .filler {
672
+ display: none;
673
+ }
674
+
675
+ @media only screen and (max-width: 1000px) {
676
+ .url-bar {
677
+ display: none;
678
+ }
679
+ .filler {
680
+ display: block;
681
+ }
682
+ }
683
+ @media only screen and (max-width: 480px) {
684
+ nav .btn2 {
685
+ width: auto !important;
686
+ min-width: 40px;
687
+ border-right: none;
688
+ flex-direction: column;
689
+ }
690
+ .app-info {
691
+ display: flex;
692
+ padding: 10px;
693
+ }
694
+ .app-info img {
695
+ width: 60px;
696
+ height: 60px;
697
+ }
698
+
699
+ .header-item {
700
+ font-size: 16px;
701
+ }
702
+ aside.active {
703
+ width: 100%;
704
+ z-index: 10000000;
705
+ }
706
+ aside:not(.active) {
707
+ display: none;
708
+ }
709
+ .container {
710
+ display: none;
711
+ }
712
+ .container.active {
713
+ display: block;
714
+ position: absolute;
715
+ z-index: 10000000;
716
+ width: 100%;
717
+ height: 100%;
718
+ }
719
+ /*
720
+ .grid-btns {
721
+ display: none;
722
+ }
723
+ */
724
+ #menu {
725
+ display: none;
726
+ }
727
+ #menu-mobile {
728
+ display: flex;
729
+ }
730
+ }
731
+ </style>
732
+ <link href="/app.css" rel="stylesheet"/>
733
+ <script src="/hotkeys.min.js"></script>
734
+ <script src="/sweetalert2.js"></script>
735
+ <script src="/nav.js"></script>
736
+ <script src="/common.js"></script>
737
+ <script src="/opener.js"></script>
738
+ <script src="/report.js"></script>
739
+ <script src="/normalize.js"></script>
740
+ <script src="/Socket.js"></script>
741
+ <script src="/noty.js"></script>
742
+ <script src="/notyq.js"></script>
743
+ <script src="/filepond-plugin-file-validate-type.min.js"></script>
744
+ <script src="/filepond-plugin-image-exif-orientation.min.js"></script>
745
+ <script src="/filepond-plugin-image-preview.min.js"></script>
746
+ <script src="/filepond-plugin-image-edit.min.js"></script>
747
+ <script src="/filepond-plugin-image-crop.min.js"></script>
748
+ <script src="/filepond-plugin-image-resize.min.js"></script>
749
+ <script src="/filepond-plugin-image-transform.min.js"></script>
750
+ <script src="/filepond.min.js"></script>
751
+ <script src="/fseditor.js"></script>
752
+ </head>
753
+ <body class='<%=theme%>' data-platform="<%=platform%>" data-agent="<%=agent%>">
754
+ <header class='navheader grabbable'>
755
+ <h1>
756
+ <a class='home' href="/"><img class='icon' src="/pinokio-black.png"></a>
757
+ <button class='btn2' id='back'><div><i class="fa-solid fa-chevron-left"></i></div><div>Prev</div></button>
758
+ <button class='btn2' id='forward'><div><i class="fa-solid fa-chevron-right"></i></div><div>Next</div></button>
759
+ <button class='btn2' id='refresh-page'><div><i class="fa-solid fa-rotate-right"></i></div><div>Refresh</div></button>
760
+ <div class='flexible filler'></div>
761
+ <div class='url-bar'>
762
+ <% if (current_urls.https) { %>
763
+ <a class='https-url' target="_blank" href="<%=current_urls.https%>"><i class="fa-solid fa-square-arrow-up-right"></i> <%=current_urls.https%></a>
764
+ <% } %>
765
+ <% if (current_urls.http) { %>
766
+ <a class='http-url' target="_blank" href="<%=current_urls.http%>"><i class="fa-solid fa-square-arrow-up-right"></i> <%=current_urls.http%></a>
767
+ <% } %>
768
+ </div>
769
+ <a href="/network" class='btn2'><div><i class="fa-solid fa-wifi"></i></div><div>Network</div></a>
770
+ <a href="/connect" class='btn2'><div><i class="fa-solid fa-circle-user"></i></div><div>Connect</div></a>
771
+ <div class='nav-btns'>
772
+ <a class='btn2' href="<%=portal%>" target="_blank"><div><i class="fa-solid fa-question"></i></div><div>Help</div></a>
773
+ <button class='btn2' id='genlog'><div><i class="fa-solid fa-laptop-code"></i></div><div>Logs</div></button>
774
+ <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>
775
+ <a class='btn2' href="/?mode=settings"><div><i class="fa-solid fa-gear"></i></div><div>Settings</div></a>
776
+ <button id='new-window' title='open a new window' class='btn2' data-agent="<%=agent%>"><div><i class="fa-solid fa-plus"></i></div><div>Window</div></button>
777
+ </div>
778
+ </h1>
779
+ </header>
780
+ <div class='appcanvas'>
781
+ <aside class='active'>
782
+ <div class='m n system' data-type="n">
783
+ <div class='dynamic'>
784
+ <% if (plugin_menu) { %>
785
+ <%- include('./partials/dynamic', { dynamic: plugin_menu, }) %>
786
+ <% } %>
787
+ </div>
788
+ </div>
789
+ </aside>
790
+ <div class='container'>
791
+ <main class='browserview'>
792
+ </main>
793
+ </div>
794
+ </div>
795
+ <script>
796
+ let started_script
797
+ let loaded = {}
798
+ let cursorIndex = 0;
799
+ let interacted = false
800
+ document.addEventListener("click", (e) => {
801
+ interacted = true
802
+ })
803
+ const n = new N()
804
+ const getTarget = (href) => {
805
+ let u
806
+ if (href.startsWith("http")) {
807
+ return href
808
+ } else if (href.startsWith("/")) {
809
+ u = new URL("http://localhost" + href)
810
+ u.search = ""
811
+ return u.pathname
812
+ } else {
813
+ u = new URL("http://localhost/" + href)
814
+ u.search = ""
815
+ return u.pathname
816
+ }
817
+ }
818
+ const subUrlOf = (s, f) => {
819
+
820
+ let subsetUrl = (s.startsWith("http") ? s : "http://localhost" + s)
821
+ let fullUrl = (f.startsWith("http") ? f: "http://localhost" + f)
822
+
823
+ const subsetParsed = new URL(subsetUrl)
824
+ const fullParsed = new URL(fullUrl)
825
+
826
+ if (subsetParsed.pathname !== fullParsed.pathname) {
827
+ return false;
828
+ }
829
+
830
+ // Check if all search parameters in the subset URL are present in the full URL
831
+ for (const [key, val] of subsetParsed.searchParams) {
832
+
833
+ if (!fullParsed.searchParams.has(key)) {
834
+ return false
835
+ }
836
+ if (fullParsed.searchParams.get(key) !== val) {
837
+ return false
838
+ }
839
+ }
840
+
841
+ return true;
842
+ }
843
+ const renderCursor = () => {
844
+ document.querySelectorAll(".selectable").forEach((el) => {
845
+ el.classList.remove("cursor")
846
+ })
847
+ const target = document.querySelector(".selectable[data-index='" + cursorIndex + "']")
848
+ target.classList.add("cursor")
849
+ }
850
+ const nav = (type) => {
851
+ let targetFrame = document.querySelector("iframe:not(.hidden)")
852
+ if (type === "back") {
853
+ // targetFrame.contentWindow.history.back()
854
+ targetFrame.contentWindow.postMessage({
855
+ action: "back"
856
+ }, "*")
857
+ } else if (type === "forward") {
858
+ // targetFrame.contentWindow.history.forward()
859
+ targetFrame.contentWindow.postMessage({
860
+ action: "forward"
861
+ }, "*")
862
+ }
863
+
864
+
865
+
866
+ // if (location.hash && location.hash.length > 0) {
867
+ //// let id = getTarget(location.hash.slice(1))
868
+ //// let target = document.querySelector("aside [target='" + id + "']")
869
+ // let id = location.hash.slice(1)
870
+ // let type = id[0]
871
+ // let index = id.slice(1)
872
+ // let target = document.querySelector(`aside .${type} [data-index='${index}']`)
873
+ // let targetFrame = document.querySelector(`iframe[name='${target.target}']`)
874
+ // console.log({ target, targetFrame })
875
+ // if (type === "back") {
876
+ // targetFrame.contentWindow.history.back()
877
+ // } else if (type === "forward") {
878
+ // targetFrame.contentWindow.history.forward()
879
+ // }
880
+ // /*
881
+ // targetFrame.contentWindow.postMessage({
882
+ // action: type
883
+ // }, "*")
884
+ // */
885
+ // }
886
+ }
887
+ const renderSelection = (e, force) => {
888
+ let selection = null
889
+ console.log({ selection })
890
+ if (selection || location.hash && location.hash.length > 0) {
891
+ let target
892
+ if (location.hash && location.hash.length > 0) {
893
+ let id = location.hash.slice(1)
894
+ let selector
895
+ if (id.startsWith("@")) {
896
+ //selector = `aside [target='${id.slice(1)}']`
897
+ selector = `aside [target='${id}']`
898
+ } else {
899
+ let type = id[0]
900
+ let index = id.slice(1)
901
+ console.log({ type, index })
902
+ selector = `aside .${type} [data-index='${index}']`
903
+ }
904
+
905
+
906
+ // select the selected link
907
+ // document.querySelectorAll(".frame-link").forEach((el) => {
908
+ // el.classList.remove("selected")
909
+ // })
910
+
911
+
912
+
913
+ // const target = document.querySelector(`[target='${id}']`)
914
+
915
+
916
+ if (e) {
917
+ // If the renderSelection is triggered by an event, look for the frame-link that's triggering the event
918
+ if (e.target.classList.contains("frame-link")) {
919
+ target = e.target
920
+ } else {
921
+ target = e.target.closest(".frame-link")
922
+ }
923
+ } else {
924
+ // if not triggered by an event, look for the target from the location hash
925
+ target = document.querySelector(selector)
926
+ }
927
+ } else {
928
+ if (selection) {
929
+ target = selection
930
+ }
931
+ }
932
+
933
+
934
+ // if the target was found either through:
935
+ // 1. looking for the frame-link that triggered the event
936
+ // 2. or by looking at the location hash
937
+ //
938
+ // => select that tab and frame
939
+
940
+ if (target) {
941
+
942
+ // display the menu button at the top
943
+ // maximize container
944
+ // minimize aside
945
+
946
+ document.querySelector(".container").classList.add("active")
947
+ document.querySelector("aside").classList.remove("active")
948
+ } else {
949
+ document.querySelector(".container").classList.remove("active")
950
+ document.querySelector("aside").classList.add("active")
951
+ }
952
+
953
+ if (target) {
954
+
955
+
956
+ // Instantiate a frame with the selected target's href
957
+ let url = target.href
958
+
959
+ if (!url) {
960
+ return
961
+ }
962
+ // document.querySelector("#open-browser").href = url
963
+ // document.querySelector("#clone-tab").setAttribute("data-href", url)
964
+
965
+ //document.querySelector("#location").value = url
966
+
967
+ // document.querySelector("#open-location").setAttribute('href', target.href)
968
+ // if (target.pathname.startsWith("/run")) {
969
+ // document.querySelector("#location").value = target.pathname.slice(4)
970
+ // } else if (target.pathname.startsWith("/api")) {
971
+ // document.querySelector("#location").value = target.pathname
972
+ // } else {
973
+ // document.querySelector("#location").value = target.href
974
+ // }
975
+
976
+
977
+ // select the selected target element (tab)
978
+ document.querySelectorAll(".frame-link").forEach((el) => {
979
+ el.classList.remove("selected")
980
+ })
981
+ target.classList.add("selected")
982
+
983
+ // hide all frames
984
+ document.querySelectorAll("iframe").forEach((el) => {
985
+ el.classList.add("hidden")
986
+ })
987
+
988
+
989
+
990
+ // Look for the frame
991
+ // 1. if it's hard (".h")
992
+ // look for the url that matches
993
+ // 2. if it's soft (".s")
994
+ // find using the name attribute
995
+ let targetFrame;
996
+ if (target.closest(".h")) {
997
+ let hardFrames = document.querySelectorAll(".browserview iframe[name^='@']")
998
+ let port = new URL(target.href).port || 80
999
+ for(let frame of hardFrames) {
1000
+ console.log({ src: frame.src, href: target.href, target: target.target })
1001
+ // Types of links in the tab
1002
+ if (String(port) === "<%=port%>") {
1003
+ // 1. running from <%=port%> => find a frame whose base URL matches the tab's base URL
1004
+ // Pinokio links
1005
+ let targetPath = new URL(target.href).pathname
1006
+ let framePath = new URL(frame.src).pathname
1007
+ if (targetPath === framePath) {
1008
+ let beforeName = frame.name
1009
+ frame.name = target.target
1010
+ console.log("SET FRAME", { before: beforeName, after: frame.name, target: target.target })
1011
+ targetFrame = frame
1012
+ break
1013
+ }
1014
+ } else {
1015
+ // 2. rest => find the frame whose src exactly matches the tab's url
1016
+ if (target.href === frame.src) {
1017
+ frame.name = target.target
1018
+ targetFrame = frame
1019
+ break
1020
+ }
1021
+ }
1022
+ // find the frame whose path matches
1023
+ }
1024
+ } else if (target.closest(".s")) {
1025
+ targetFrame = document.querySelector(`iframe[name='${target.target}']`)
1026
+ } else if (target.closest(".n")) {
1027
+ targetFrame = document.querySelector(`iframe[name='${target.target}']`)
1028
+ }
1029
+
1030
+ /*
1031
+ // Load the link in the frame
1032
+
1033
+ 1. if the frame was found:
1034
+ - if "refresh": true => refresh
1035
+ - otherwise,
1036
+ - if the target frame has been already loaded, don't do anything
1037
+ - frame: start.json?mode=abc, link: start.json?mode=abc => don't touch
1038
+ - link === frame
1039
+ - frame: start.json?mode=abc, link: start.json?mode=def => should load
1040
+ - link !== frame && !frame.includes(link)
1041
+ - frame: start.json?mode=abc, link: start.json => don't touch
1042
+ - link !== frame && frame.includes(link)
1043
+
1044
+
1045
+
1046
+ if the link is different
1047
+
1048
+ - if the target frame has not been loaded, refresh
1049
+ 2. if the frame was NOT found => create one
1050
+
1051
+ */
1052
+
1053
+ if (targetFrame) {
1054
+ targetFrame.classList.remove("hidden")
1055
+ let mode = target.getAttribute("data-mode")
1056
+ if (mode === "refresh") {
1057
+ targetFrame.src = target.href
1058
+ } else {
1059
+ if (e) {
1060
+ if (target.closest(".h")) {
1061
+ e.preventDefault()
1062
+ e.stopPropagation()
1063
+ let sub = subUrlOf(target.href, targetFrame.src)
1064
+ if (!sub) {
1065
+ targetFrame.src = target.href
1066
+ }
1067
+ //if (target.href === targetFrame.src) {
1068
+ // // same url. don't do anything
1069
+ // e.preventDefault()
1070
+ // e.stopPropagation()
1071
+ //} else {
1072
+ // if (targetFrame.src.includes(target.href)) {
1073
+ // // different url, but the frame's url contains the tab url => don't touch
1074
+ // e.preventDefault()
1075
+ // e.stopPropagation()
1076
+ // } else {
1077
+ // // different url, and the frame's url does not contain the tab url => change the src of the frame and load
1078
+ // targetFrame.src = target.href
1079
+ // e.preventDefault()
1080
+ // e.stopPropagation()
1081
+ // }
1082
+ //}
1083
+ } else if (target.closest(".s")) {
1084
+ // load unconditionally => .s doesn't change
1085
+ e.preventDefault()
1086
+ e.stopPropagation()
1087
+ } else if (target.closest(".n")) {
1088
+ // load unconditionally => .n doesn't change
1089
+ e.preventDefault()
1090
+ e.stopPropagation()
1091
+ }
1092
+ } else {
1093
+ if (force) {
1094
+ targetFrame.src = target.href
1095
+ }
1096
+ }
1097
+ targetFrame.contentWindow.postMessage({
1098
+ action: "foreground"
1099
+ }, "*")
1100
+ }
1101
+ } else {
1102
+ let frame = document.createElement("iframe")
1103
+ frame.name = target.target
1104
+ frame.src = target.href
1105
+ frame.setAttribute(
1106
+ "allow",
1107
+ "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 *;"
1108
+ )
1109
+ document.querySelector("main").appendChild(frame)
1110
+ loaded[target.target] = true
1111
+ }
1112
+
1113
+ // if (targetFrame) {
1114
+ // targetFrame.classList.remove("hidden")
1115
+ //
1116
+ // // if the iframe already exists, do not
1117
+ // if (loaded[target.target]){
1118
+ //
1119
+ // // Force refresh option
1120
+ // //
1121
+ // // menu := [{
1122
+ // // text,
1123
+ // // icon,
1124
+ // // mode: "refresh" => refresh regardless of any condition
1125
+ // // }]
1126
+ // let mode = target.getAttribute("data-mode")
1127
+ // if (mode === "refresh") {
1128
+ // targetFrame.src = target.href
1129
+ // } else {
1130
+ // console.log("# 4")
1131
+ // if (e) {
1132
+ // // if triggered by a click event,
1133
+ // // 1. if it's a hard link (".h")
1134
+ // // - ignore if the pathname is the same
1135
+ // // - reload if
1136
+ // console.log("# 5", { src: targetFrame.src, href: target.href, target: target.target })
1137
+ // // triggered with a click
1138
+ // // do not reload iframe if the href and the src is the same
1139
+ // if (target.closest(".h")) {
1140
+ // // if (targetFrame.src.includes(target.target)) {
1141
+ // if (targetFrame.src.includes(target.href)) {
1142
+ // // if (targetFrame.src === target.href) {
1143
+ // e.preventDefault()
1144
+ // e.stopPropagation()
1145
+ // }
1146
+ // } else if (target.closest(".s")) {
1147
+ // e.preventDefault()
1148
+ // e.stopPropagation()
1149
+ // }
1150
+ // } else {
1151
+ // // if not triggered by event
1152
+ // // refresh ONLY if programmatically forced refresh
1153
+ // console.log("# 6")
1154
+ // if (force) {
1155
+ // console.log("# 7")
1156
+ // targetFrame.src = target.href
1157
+ // }
1158
+ // }
1159
+ // }
1160
+ //
1161
+ // } else {
1162
+ // console.log("# 8")
1163
+ // //targetFrame.contentWindow.addEventListener("load", () => {
1164
+ // if (e) {
1165
+ // console.log("# 9")
1166
+ // // coming from a click => don't need to set the src
1167
+ // } else {
1168
+ // console.log("# 10")
1169
+ // // load without click
1170
+ // if (targetFrame.src !== target.href) {
1171
+ // console.log("# 11")
1172
+ // targetFrame.src = target.href
1173
+ // }
1174
+ // }
1175
+ // loaded[target.target] = true
1176
+ // //});
1177
+ // }
1178
+ // } else {
1179
+ // console.log("# 12")
1180
+ // let frame = document.createElement("iframe")
1181
+ // frame.name = target.target
1182
+ // frame.src = target.href
1183
+ // frame.setAttribute(
1184
+ // "allow",
1185
+ // "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 *;"
1186
+ // )
1187
+ // document.querySelector("main").appendChild(frame)
1188
+ // loaded[target.target] = true
1189
+ // }
1190
+ } else {
1191
+ console.log("# 13")
1192
+ // couldn't find item,
1193
+ // clear the hash
1194
+ //
1195
+ location.hash = ""
1196
+ }
1197
+ } else {
1198
+ console.log("# 14")
1199
+ document.querySelector(".container").classList.remove("active")
1200
+ document.querySelector("aside").classList.add("active")
1201
+
1202
+ }
1203
+ }
1204
+ renderSelection()
1205
+ //renderCursor()
1206
+ //Reporter()
1207
+ <% if (agent === "electron") { %>
1208
+ document.querySelector("#back").addEventListener("click", (e) => {
1209
+ nav("back")
1210
+ })
1211
+ document.querySelector("#forward").addEventListener("click", (e) => {
1212
+ nav("forward")
1213
+ })
1214
+ <% } %>
1215
+
1216
+
1217
+ if (document.querySelector("#menu")) {
1218
+ document.querySelector("#menu").addEventListener("click", async (e) => {
1219
+ document.querySelector("aside").classList.toggle("hidden")
1220
+ document.querySelector("#menu").classList.toggle("margin")
1221
+ })
1222
+ }
1223
+ /*
1224
+ document.querySelector("#edit-toggle").addEventListener("click", async (e) => {
1225
+ e.preventDefault()
1226
+ e.stopPropagation()
1227
+ document.querySelector(".editsubmenu").classList.toggle("hidden")
1228
+ })
1229
+ */
1230
+ document.querySelector("aside").addEventListener("click", async (e) => {
1231
+ let target
1232
+
1233
+ // 0. handle dropdowns
1234
+ if (e.target.classList.contains("revealer")) {
1235
+ target = e.target
1236
+ } else {
1237
+ target = e.target.closest(".revealer")
1238
+ }
1239
+
1240
+ if (target) {
1241
+ e.preventDefault()
1242
+ e.stopPropagation()
1243
+ let group = target.getAttribute("data-group")
1244
+ document.querySelector(group).classList.toggle("hidden")
1245
+ target.querySelector(".loader .fa-angle-down").classList.toggle("hidden")
1246
+ target.querySelector(".loader .fa-angle-up").classList.toggle("hidden")
1247
+ return
1248
+ }
1249
+
1250
+
1251
+
1252
+
1253
+ // 2. handle shudown
1254
+ if (e.target.classList.contains("shutdown")) {
1255
+ target = e.target
1256
+ } else {
1257
+ target = e.target.closest(".shutdown")
1258
+ }
1259
+ if (target) {
1260
+ e.preventDefault()
1261
+ e.stopPropagation()
1262
+ let shell = target.closest("[data-shell]")
1263
+ if (shell) {
1264
+ let shell_id = shell.getAttribute("data-shell")
1265
+ n.Noty({
1266
+ text: `stopping shell`,
1267
+ silent: true,
1268
+ timeout: 2000
1269
+ })
1270
+ let socket = new Socket()
1271
+ socket.run({
1272
+ method: "kernel.bin.shell_kill",
1273
+ params: {
1274
+ id: shell_id
1275
+ }
1276
+ }, (packet) => {
1277
+ console.log("packet", packet)
1278
+ if (packet.type === "result") {
1279
+ socket.close()
1280
+ n.Noty({
1281
+ timeout: 2000,
1282
+ text: `stopped`,
1283
+ silent: true
1284
+ })
1285
+ console.log("Refresh 4")
1286
+ refresh(true)
1287
+ }
1288
+ })
1289
+ } else {
1290
+ let script = target.closest("[data-script]")
1291
+ if (script) {
1292
+ let script_id = script.getAttribute("data-script")
1293
+ target.querySelector("i.fa-square").className = "fa-solid fa-check"
1294
+ n.Noty({
1295
+ text: `stopping script`,
1296
+ silent: true,
1297
+ timeout: 2000
1298
+ })
1299
+
1300
+ let socket = new Socket()
1301
+ socket.run({
1302
+ method: "kernel.api.stop",
1303
+ params: {
1304
+ id: script_id
1305
+ }
1306
+ }, (packet) => {
1307
+ if (packet.type === "result") {
1308
+ socket.close()
1309
+ n.Noty({
1310
+ timeout: 2000,
1311
+ text: `stopped`,
1312
+ silent: true
1313
+ })
1314
+ console.log("Refresh 4")
1315
+ refresh(true)
1316
+ }
1317
+ })
1318
+ } else {
1319
+ let link = target.closest("[href]")
1320
+ if (link) {
1321
+ let src = new URL(link.href).pathname
1322
+ target.querySelector("i.fa-square").className = "fa-solid fa-check"
1323
+ n.Noty({
1324
+ text: `stopping ${src}`,
1325
+ silent: true,
1326
+ timeout: 2000
1327
+ })
1328
+ console.log("src", src)
1329
+
1330
+ let socket = new Socket()
1331
+ socket.run({
1332
+ method: "kernel.api.stop",
1333
+ params: {
1334
+ uri: "~" + src
1335
+ }
1336
+ }, (packet) => {
1337
+ if (packet.type === "result") {
1338
+ socket.close()
1339
+ n.Noty({
1340
+ timeout: 2000,
1341
+ text: `stopped`,
1342
+ silent: true
1343
+ })
1344
+ console.log("Refresh 4")
1345
+ refresh(true)
1346
+ }
1347
+ })
1348
+ }
1349
+ }
1350
+ }
1351
+
1352
+ return
1353
+ }
1354
+
1355
+
1356
+
1357
+ // 3. handle select
1358
+ if (e.target.classList.contains("frame-link")) {
1359
+ target = e.target
1360
+ } else {
1361
+ target = e.target.closest(".frame-link")
1362
+ }
1363
+
1364
+
1365
+
1366
+ if (target) {
1367
+
1368
+ // if data-confirm exists, ask for confirmation
1369
+ // if not, then just go forward
1370
+ let confirmText = target.getAttribute("data-confirm")
1371
+ if (confirmText && confirmText.length > 0) {
1372
+ const confirmed = confirm(confirmText)
1373
+ if (!confirmed) {
1374
+ e.preventDefault()
1375
+ e.stopPropagation()
1376
+ return
1377
+ }
1378
+ }
1379
+
1380
+ if (target.getAttribute("data-action")) {
1381
+ let actionStr = target.getAttribute("data-action")
1382
+ let action = JSON.parse(actionStr)
1383
+ console.log("action", action)
1384
+ if (action.method === "stop" && action.uri) {
1385
+ let socket = new Socket()
1386
+ socket.run({
1387
+ method: "kernel.api.stop",
1388
+ params: {
1389
+ uri: action.uri//"~" + location.pathname
1390
+ }
1391
+ }, (packet) => {
1392
+ if (packet.type === "result") {
1393
+ socket.close()
1394
+ // location.href = location.href
1395
+ }
1396
+ })
1397
+ }
1398
+ } else if (target.getAttribute("data-filepath")) {
1399
+ return
1400
+ } else if (target.target === "_blank") {
1401
+ // nothing
1402
+ } else {
1403
+ if (target.classList.contains("reveal")) {
1404
+ // nested menu
1405
+ e.preventDefault()
1406
+ e.stopPropagation()
1407
+ // dev mode => already dev. reveal the hidden menu
1408
+ if (target.closest(".dynamic")) {
1409
+ target.closest(".dynamic").classList.toggle("selected")
1410
+ target.closest(".nested-menu").querySelector(".submenu").classList.toggle("hidden")
1411
+ target.querySelector(".loader .fa-angle-down").classList.toggle("hidden")
1412
+ target.querySelector(".loader .fa-angle-up").classList.toggle("hidden")
1413
+ } else {
1414
+ target.closest(".nested-menu").querySelector(".submenu").classList.toggle("hidden")
1415
+ target.querySelector(".loader .fa-angle-down").classList.toggle("hidden")
1416
+ target.querySelector(".loader .fa-angle-up").classList.toggle("hidden")
1417
+ }
1418
+ return
1419
+ } else {
1420
+ //location.hash = target.target
1421
+
1422
+
1423
+ // let id = getTarget(target.getAttribute("href"))
1424
+ // console.log("ID", id, target.href)
1425
+ // location.hash = id
1426
+
1427
+ //location.hash = target.getAttribute("href")
1428
+
1429
+ if (target.closest(".h")) {
1430
+ if (target.target) {
1431
+ location.hash = target.target
1432
+ }
1433
+ } else {
1434
+ let index = target.getAttribute("data-index")
1435
+ let type = target.closest(".m").getAttribute("data-type")
1436
+
1437
+
1438
+ if (type) {
1439
+ location.hash = type + index
1440
+ }
1441
+ }
1442
+
1443
+ document.querySelectorAll(".frame-link").forEach((el) => {
1444
+ el.classList.remove("selected")
1445
+ })
1446
+ target.classList.add("selected")
1447
+
1448
+ renderSelection(e)
1449
+ }
1450
+ }
1451
+ }
1452
+
1453
+
1454
+
1455
+ })
1456
+ const refresh = async (silent, options) => {
1457
+ console.log("REFRESH")
1458
+ const dynamic = await fetch("<%=dynamic%>").then((res) => {
1459
+ return res.text()
1460
+ })
1461
+ console.log({ dynamic })
1462
+ if (document.querySelector(".dynamic")) {
1463
+ document.querySelector(".dynamic").innerHTML = dynamic
1464
+ }
1465
+ }
1466
+ if (document.querySelector("#genlog")) {
1467
+ document.querySelector("#genlog").addEventListener("click", (e) => {
1468
+ e.preventDefault()
1469
+ e.stopPropagation()
1470
+ e.target.innerHTML = '<i class="fa-solid fa-circle-notch fa-spin"></i>'
1471
+ fetch("/pinokio/log", {
1472
+ method: "post",
1473
+ }).then((res) => {
1474
+ console.log("RES", res)
1475
+ let btn = document.querySelector("#genlog")
1476
+ let btn2 = document.querySelector("#downloadlogs")
1477
+ btn2.classList.remove("hidden")
1478
+ btn.classList.add("hidden")
1479
+ btn.innerHTML = '<i class="fa-solid fa-circle-check"></i> Generated!'
1480
+ //btn.classList.add("hidden")
1481
+ })
1482
+ })
1483
+ }
1484
+ let init = document.querySelector("[data-init]")
1485
+ console.log("init")
1486
+ if (init) {
1487
+ init.click()
1488
+ }
1489
+ /*
1490
+ window.addEventListener("hashchange", function () {
1491
+ console.log("Hash changed:", location.hash);
1492
+ location.reload()
1493
+ });
1494
+ */
1495
+ window.addEventListener('message', (event) => {
1496
+ refresh()
1497
+ console.log("EVENT" ,event.data)
1498
+
1499
+ // only process the event it's coming from pinokio
1500
+ let origin = event.origin
1501
+ if (origin) {
1502
+ let port = new URL(origin).port || 80
1503
+ console.log("port", port)
1504
+ if (String(port) === "<%=port%>") {
1505
+ console.log("Message received from the child: ", event); // Message received from child
1506
+ if (event.type === "start") {
1507
+ location.href = location.href
1508
+ }
1509
+ if (event.data) {
1510
+ if (event.data.action) {
1511
+ if (event.data.action.type === "newtab") {
1512
+ console.log("create tab", event.data.action.url)
1513
+ } else if (event.data.action.type === "title") {
1514
+ console.log("title", event.data)
1515
+ } else if (event.data.action.type === "location") {
1516
+ console.log("EVENT", event)
1517
+ let url = event.data.action.url
1518
+ console.log({ action: event.data.action })
1519
+
1520
+ //document.querySelector("#location").value = url
1521
+ let pathname = new URL(url).pathname
1522
+ if (pathname.startsWith("/run")) {
1523
+ document.querySelector("#location").value = pathname.slice(4)
1524
+ } else {
1525
+ document.querySelector("#location").value = pathname
1526
+ }
1527
+ }
1528
+ } else if (event.data.type) {
1529
+ }
1530
+ } else {
1531
+ }
1532
+ }
1533
+ }
1534
+
1535
+
1536
+ });
1537
+ if (document.querySelector(".dynamic .reveal")) {
1538
+ document.querySelector(".dynamic .reveal").click()
1539
+ }
1540
+ </script>
1541
+ </body>
1542
+ </html>