pinokiod 3.108.0 → 3.110.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/bin/caddy.js +20 -0
- package/kernel/git.js +21 -23
- package/kernel/peer.js +2 -1
- package/package.json +1 -1
- package/server/index.js +89 -73
- package/server/public/layout.js +21 -0
- package/server/views/app.ejs +251 -40
- package/server/views/file_explorer.ejs +1 -1
- package/server/views/index.ejs +1 -1
- package/server/views/index2.ejs +1 -1
- package/server/views/partials/dynamic.ejs +1 -1
- package/server/views/partials/menu.ejs +1 -1
package/kernel/bin/caddy.js
CHANGED
|
@@ -23,6 +23,26 @@ class Caddy {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
async start() {
|
|
26
|
+
// if peer.https_active is true,
|
|
27
|
+
// 1. kill existing caddy
|
|
28
|
+
// 2. start caddy
|
|
29
|
+
if (!this.kernel.peer || !("https_active" in this.kernel.peer)) {
|
|
30
|
+
// wait until they are available
|
|
31
|
+
await new Promise((resolve, reject) => {
|
|
32
|
+
let interval = setInterval(() => {
|
|
33
|
+
console.log("wait until peer becomes available")
|
|
34
|
+
if (this.kernel.peer && "https_active" in this.kernel.peer) {
|
|
35
|
+
console.log("peer ready")
|
|
36
|
+
clearInterval(interval)
|
|
37
|
+
resolve()
|
|
38
|
+
}
|
|
39
|
+
}, 1000)
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
if (!this.kernel.peer.https_active) {
|
|
43
|
+
console.log("https_active false")
|
|
44
|
+
return
|
|
45
|
+
}
|
|
26
46
|
// console.log("Existing caddy pid?", this.kernel.processes.caddy_pid)
|
|
27
47
|
let running = await this.running()
|
|
28
48
|
console.log("Caddy running?", running)
|
package/kernel/git.js
CHANGED
|
@@ -67,41 +67,39 @@ class Git {
|
|
|
67
67
|
display_name = `${name}/${gitRelPathSansGit}`
|
|
68
68
|
main = false
|
|
69
69
|
}
|
|
70
|
+
let gitRemote = null
|
|
70
71
|
try {
|
|
71
|
-
|
|
72
|
+
gitRemote = await git.getConfig({
|
|
72
73
|
fs,
|
|
73
74
|
http,
|
|
74
75
|
dir,
|
|
75
76
|
path: 'remote.origin.url'
|
|
76
77
|
})
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
78
|
+
} catch (_) {}
|
|
79
|
+
|
|
80
|
+
const repoEntry = {
|
|
81
|
+
main,
|
|
82
|
+
name: display_name,
|
|
83
|
+
gitPath,
|
|
84
|
+
gitRelPath,
|
|
85
|
+
gitParentPath,
|
|
86
|
+
gitParentRelPath,
|
|
87
|
+
dir,
|
|
88
|
+
}
|
|
89
|
+
if (gitRemote) {
|
|
90
|
+
repoEntry.url = gitRemote
|
|
91
|
+
}
|
|
92
|
+
repos.push(repoEntry)
|
|
93
|
+
|
|
94
|
+
if (gitRemote && !this.mapping[gitRemote]) {
|
|
95
|
+
try {
|
|
88
96
|
let head = await this.getHead(gitParentPath)
|
|
89
97
|
this.mapping[gitRemote] = {
|
|
90
98
|
main,
|
|
91
99
|
path: gitParentPath,
|
|
92
100
|
head
|
|
93
101
|
}
|
|
94
|
-
}
|
|
95
|
-
} catch (e) {
|
|
96
|
-
repos.push({
|
|
97
|
-
main,
|
|
98
|
-
name: display_name,
|
|
99
|
-
gitPath,
|
|
100
|
-
gitRelPath,
|
|
101
|
-
gitParentPath,
|
|
102
|
-
gitParentRelPath,
|
|
103
|
-
dir,
|
|
104
|
-
})
|
|
102
|
+
} catch (_) {}
|
|
105
103
|
}
|
|
106
104
|
this.dirs.add(dir)
|
|
107
105
|
}
|
package/kernel/peer.js
CHANGED
|
@@ -249,7 +249,7 @@ class PeerDiscovery {
|
|
|
249
249
|
async router_info() {
|
|
250
250
|
try {
|
|
251
251
|
let processes = []
|
|
252
|
-
if (this.info[this.host]) {
|
|
252
|
+
if (this.info && this.info[this.host]) {
|
|
253
253
|
let procs = this.info[this.host].proc
|
|
254
254
|
let router = this.info[this.host].router
|
|
255
255
|
let port_mapping = this.info[this.host].port_mapping
|
|
@@ -406,6 +406,7 @@ class PeerDiscovery {
|
|
|
406
406
|
}
|
|
407
407
|
return {
|
|
408
408
|
active: this.active,
|
|
409
|
+
https_active: this.https_active,
|
|
409
410
|
version: this.kernel.version,
|
|
410
411
|
home: this.kernel.homedir,
|
|
411
412
|
arch: this.kernel.arch,
|
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -484,98 +484,112 @@ class Server {
|
|
|
484
484
|
}
|
|
485
485
|
}
|
|
486
486
|
async getGit(ref, filepath) {
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
if (branches.length === 0) {
|
|
491
|
-
return {}
|
|
492
|
-
// const defaultBranch = 'main';
|
|
493
|
-
// await git.init({ fs, dir, defaultBranch });
|
|
494
|
-
// branches = await git.listBranches({ fs, dir });
|
|
495
|
-
// const current = await git.currentBranch({ fs, dir, fullname: false }) || defaultBranch;
|
|
496
|
-
// if (!branches.includes(current)) {
|
|
497
|
-
// branches.unshift(current);
|
|
498
|
-
// }
|
|
499
|
-
// if (!ref || ref === 'HEAD') {
|
|
500
|
-
// ref = current;
|
|
501
|
-
// }
|
|
502
|
-
}
|
|
503
|
-
let log = []
|
|
487
|
+
const dir = this.kernel.path("api", filepath)
|
|
488
|
+
|
|
489
|
+
let branchList = []
|
|
504
490
|
try {
|
|
505
|
-
|
|
506
|
-
|
|
491
|
+
branchList = await git.listBranches({ fs, dir })
|
|
492
|
+
} catch (_) {}
|
|
493
|
+
|
|
494
|
+
const collectLog = async (targetRef) => {
|
|
495
|
+
const entries = await git.log({ fs, dir, depth: 50, ref: targetRef })
|
|
496
|
+
entries.forEach((item) => {
|
|
507
497
|
item.info = `/gitcommit/${item.oid}/${filepath}`
|
|
508
498
|
})
|
|
509
|
-
|
|
510
|
-
|
|
499
|
+
return entries
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
let log = []
|
|
503
|
+
let logError = null
|
|
504
|
+
if (ref) {
|
|
505
|
+
try {
|
|
506
|
+
log = await collectLog(ref)
|
|
507
|
+
} catch (error) {
|
|
508
|
+
logError = error
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
if (log.length === 0) {
|
|
512
|
+
try {
|
|
513
|
+
log = await collectLog('HEAD')
|
|
514
|
+
} catch (error) {
|
|
515
|
+
if (!logError) {
|
|
516
|
+
logError = error
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
let currentBranch = null
|
|
522
|
+
try {
|
|
523
|
+
currentBranch = await git.currentBranch({ fs, dir, fullname: false })
|
|
524
|
+
} catch (_) {}
|
|
525
|
+
|
|
526
|
+
let branches = []
|
|
527
|
+
if (branchList.length > 0) {
|
|
528
|
+
branches = branchList.map((name) => ({
|
|
529
|
+
branch: name,
|
|
530
|
+
selected: currentBranch ? name === currentBranch : false
|
|
531
|
+
}))
|
|
532
|
+
if (!currentBranch && log.length > 0) {
|
|
533
|
+
const headOid = log[0].oid
|
|
534
|
+
branches = [{ branch: headOid, selected: true }, ...branches.map((entry) => ({ ...entry, selected: false }))]
|
|
535
|
+
currentBranch = headOid
|
|
536
|
+
}
|
|
537
|
+
} else {
|
|
538
|
+
if (currentBranch) {
|
|
539
|
+
branches = [{ branch: currentBranch, selected: true }]
|
|
540
|
+
} else if (log.length > 0) {
|
|
541
|
+
const headOid = log[0].oid
|
|
542
|
+
branches = [{ branch: headOid, selected: true }]
|
|
543
|
+
currentBranch = headOid
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
if (!currentBranch && log.length > 0) {
|
|
548
|
+
currentBranch = log[0].oid
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
if (branches.length === 0) {
|
|
552
|
+
branches = [{ branch: currentBranch || 'HEAD', selected: true }]
|
|
511
553
|
}
|
|
512
554
|
|
|
513
|
-
|
|
555
|
+
const config = await this.kernel.git.config(dir)
|
|
514
556
|
|
|
515
557
|
let hosts = ""
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
hosts = await fs.promises.readFile(hosts_file, "utf8")
|
|
558
|
+
const hostsFile = this.kernel.path("config/gh/hosts.yml")
|
|
559
|
+
if (await this.exists(hostsFile)) {
|
|
560
|
+
hosts = await fs.promises.readFile(hostsFile, "utf8")
|
|
520
561
|
if (hosts.startsWith("{}")) {
|
|
521
562
|
hosts = ""
|
|
522
563
|
}
|
|
523
564
|
}
|
|
524
|
-
|
|
565
|
+
const connected = hosts.length > 0
|
|
566
|
+
|
|
525
567
|
let remote = null
|
|
526
|
-
if (config["remote \"origin\""]) {
|
|
568
|
+
if (config && config["remote \"origin\""]) {
|
|
527
569
|
remote = config["remote \"origin\""].url
|
|
528
570
|
}
|
|
529
571
|
|
|
530
|
-
// Get all remotes
|
|
531
572
|
let remotes = []
|
|
532
573
|
try {
|
|
533
574
|
remotes = await git.listRemotes({ fs, dir, verbose: true })
|
|
534
|
-
} catch (
|
|
535
|
-
console.log("Remotes error", e)
|
|
536
|
-
}
|
|
575
|
+
} catch (_) {}
|
|
537
576
|
|
|
538
|
-
|
|
577
|
+
if (!currentBranch) {
|
|
578
|
+
currentBranch = 'HEAD'
|
|
579
|
+
}
|
|
539
580
|
|
|
540
|
-
|
|
541
|
-
|
|
581
|
+
return {
|
|
582
|
+
ref,
|
|
583
|
+
config,
|
|
584
|
+
remote,
|
|
585
|
+
remotes,
|
|
586
|
+
connected,
|
|
587
|
+
log,
|
|
588
|
+
branch: currentBranch,
|
|
589
|
+
branches,
|
|
542
590
|
dir,
|
|
543
|
-
|
|
544
|
-
});
|
|
545
|
-
|
|
546
|
-
// if current branch exitss => currengt branch is selected
|
|
547
|
-
// if current branch does not exist => get logs[0].oid
|
|
548
|
-
if (branch) {
|
|
549
|
-
branches = branches.map((b) => {
|
|
550
|
-
if (b === branch) {
|
|
551
|
-
return {
|
|
552
|
-
branch: b,
|
|
553
|
-
selected: true
|
|
554
|
-
}
|
|
555
|
-
} else {
|
|
556
|
-
return {
|
|
557
|
-
branch: b,
|
|
558
|
-
selected: false
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
})
|
|
562
|
-
} else {
|
|
563
|
-
branches.push(log[0].oid)
|
|
564
|
-
branches = branches.map((b) => {
|
|
565
|
-
if (b === log[0].oid) {
|
|
566
|
-
return {
|
|
567
|
-
branch: b,
|
|
568
|
-
selected: true
|
|
569
|
-
}
|
|
570
|
-
} else {
|
|
571
|
-
return {
|
|
572
|
-
branch: b,
|
|
573
|
-
selected: false
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
})
|
|
591
|
+
logError: logError ? String(logError.message || logError) : null
|
|
577
592
|
}
|
|
578
|
-
return { ref, config, remote, remotes, connected, log, branch, branches, dir }
|
|
579
593
|
}
|
|
580
594
|
async init_env(env_dir_path, options) {
|
|
581
595
|
let current = this.kernel.path(env_dir_path, "ENVIRONMENT")
|
|
@@ -4084,11 +4098,14 @@ class Server {
|
|
|
4084
4098
|
defaultUrl.searchParams.set('mode', 'settings')
|
|
4085
4099
|
}
|
|
4086
4100
|
|
|
4101
|
+
const initialPath = initialUrl.pathname + initialUrl.search + initialUrl.hash
|
|
4102
|
+
const defaultPath = defaultUrl.pathname + defaultUrl.search + defaultUrl.hash
|
|
4103
|
+
|
|
4087
4104
|
res.render('layout', {
|
|
4088
4105
|
theme: this.theme,
|
|
4089
4106
|
agent: req.agent,
|
|
4090
|
-
initialPath
|
|
4091
|
-
defaultPath
|
|
4107
|
+
initialPath,
|
|
4108
|
+
defaultPath,
|
|
4092
4109
|
sessionId: typeof req.query.session === 'string' ? req.query.session : null
|
|
4093
4110
|
})
|
|
4094
4111
|
}))
|
|
@@ -5532,7 +5549,6 @@ class Server {
|
|
|
5532
5549
|
// }))
|
|
5533
5550
|
this.app.post("/env", ex(async (req, res) => {
|
|
5534
5551
|
let fullpath = path.resolve(this.kernel.homedir, req.body.filepath, "ENVIRONMENT")
|
|
5535
|
-
console.log({ fullpath })
|
|
5536
5552
|
let updated = req.body.vals
|
|
5537
5553
|
let hosts = req.body.hosts
|
|
5538
5554
|
await Util.update_env(fullpath, updated)
|
package/server/public/layout.js
CHANGED
|
@@ -37,6 +37,26 @@
|
|
|
37
37
|
const leafElements = new Map();
|
|
38
38
|
const gutterElements = new Map();
|
|
39
39
|
const layoutCache = new Map();
|
|
40
|
+
const PRESERVED_QUERY_PARAMS = new Set(['session']);
|
|
41
|
+
|
|
42
|
+
function stripTransientQueryParams() {
|
|
43
|
+
try {
|
|
44
|
+
const url = new URL(window.location.href);
|
|
45
|
+
let changed = false;
|
|
46
|
+
const keys = Array.from(url.searchParams.keys());
|
|
47
|
+
keys.forEach((key) => {
|
|
48
|
+
if (!PRESERVED_QUERY_PARAMS.has(key)) {
|
|
49
|
+
url.searchParams.delete(key);
|
|
50
|
+
changed = true;
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
if (changed) {
|
|
54
|
+
window.history.replaceState(window.history.state, '', url.toString());
|
|
55
|
+
}
|
|
56
|
+
} catch (_) {
|
|
57
|
+
// ignore malformed URLs
|
|
58
|
+
}
|
|
59
|
+
}
|
|
40
60
|
|
|
41
61
|
function normalizeSrc(raw) {
|
|
42
62
|
if (!raw || typeof raw !== 'string') {
|
|
@@ -698,6 +718,7 @@
|
|
|
698
718
|
applyLayout();
|
|
699
719
|
attachGutterHandlers();
|
|
700
720
|
broadcastLayoutState();
|
|
721
|
+
stripTransientQueryParams();
|
|
701
722
|
}
|
|
702
723
|
|
|
703
724
|
function onResize() {
|
package/server/views/app.ejs
CHANGED
|
@@ -890,6 +890,33 @@ body.dark .tab-link-popover .tab-link-popover-item .value {
|
|
|
890
890
|
body.dark .tab-link-popover .tab-link-popover-item .value .muted {
|
|
891
891
|
color: rgba(226, 232, 240, 0.65);
|
|
892
892
|
}
|
|
893
|
+
.tab-link-popover .tab-link-popover-footer {
|
|
894
|
+
border-top: 1px solid rgba(15, 23, 42, 0.08);
|
|
895
|
+
margin-top: 4px;
|
|
896
|
+
padding-top: 12px;
|
|
897
|
+
background: rgba(59, 130, 246, 0.12);
|
|
898
|
+
color: #1d4ed8;
|
|
899
|
+
}
|
|
900
|
+
.tab-link-popover .tab-link-popover-footer .label,
|
|
901
|
+
.tab-link-popover .tab-link-popover-footer .value {
|
|
902
|
+
color: inherit;
|
|
903
|
+
}
|
|
904
|
+
.tab-link-popover .tab-link-popover-footer .value {
|
|
905
|
+
font-weight: 600;
|
|
906
|
+
}
|
|
907
|
+
.tab-link-popover .tab-link-popover-footer:hover,
|
|
908
|
+
.tab-link-popover .tab-link-popover-footer:focus-visible {
|
|
909
|
+
background: rgba(37, 99, 235, 0.2);
|
|
910
|
+
}
|
|
911
|
+
body.dark .tab-link-popover .tab-link-popover-footer {
|
|
912
|
+
border-top-color: rgba(148, 163, 184, 0.2);
|
|
913
|
+
background: rgba(96, 165, 250, 0.22);
|
|
914
|
+
color: #bfdbfe;
|
|
915
|
+
}
|
|
916
|
+
body.dark .tab-link-popover .tab-link-popover-footer:hover,
|
|
917
|
+
body.dark .tab-link-popover .tab-link-popover-footer:focus-visible {
|
|
918
|
+
background: rgba(147, 197, 253, 0.35);
|
|
919
|
+
}
|
|
893
920
|
.tab.has-preview .tab-preview {
|
|
894
921
|
color: rgba(0, 0, 0, 0.6);
|
|
895
922
|
min-width: 0;
|
|
@@ -1947,6 +1974,40 @@ body.dark {
|
|
|
1947
1974
|
background: #2d6ae0 !important;
|
|
1948
1975
|
}
|
|
1949
1976
|
|
|
1977
|
+
.pinokio-github-login-modal.swal2-popup {
|
|
1978
|
+
max-width: 420px !important;
|
|
1979
|
+
width: calc(100vw - 48px) !important;
|
|
1980
|
+
}
|
|
1981
|
+
.pinokio-github-login {
|
|
1982
|
+
padding: 36px 40px 32px 40px;
|
|
1983
|
+
display: flex;
|
|
1984
|
+
flex-direction: column;
|
|
1985
|
+
align-items: center;
|
|
1986
|
+
text-align: center;
|
|
1987
|
+
gap: 14px;
|
|
1988
|
+
}
|
|
1989
|
+
.pinokio-github-login__icon {
|
|
1990
|
+
width: 64px;
|
|
1991
|
+
height: 64px;
|
|
1992
|
+
border-radius: 18px;
|
|
1993
|
+
display: grid;
|
|
1994
|
+
place-items: center;
|
|
1995
|
+
background: var(--pinokio-modal-icon-bg);
|
|
1996
|
+
color: var(--pinokio-modal-icon-color);
|
|
1997
|
+
font-size: 28px;
|
|
1998
|
+
}
|
|
1999
|
+
.pinokio-github-login__title {
|
|
2000
|
+
font-size: 20px;
|
|
2001
|
+
font-weight: 600;
|
|
2002
|
+
color: var(--pinokio-modal-text);
|
|
2003
|
+
}
|
|
2004
|
+
.pinokio-github-login__body {
|
|
2005
|
+
font-size: 14px;
|
|
2006
|
+
line-height: 1.6;
|
|
2007
|
+
color: var(--pinokio-modal-subtitle-color);
|
|
2008
|
+
max-width: 280px;
|
|
2009
|
+
}
|
|
2010
|
+
|
|
1950
2011
|
.pinokio-modern-modal.swal2-popup {
|
|
1951
2012
|
background: var(--pinokio-modal-bg) !important;
|
|
1952
2013
|
color: var(--pinokio-modal-text) !important;
|
|
@@ -3054,6 +3115,7 @@ body.dark {
|
|
|
3054
3115
|
let tabLinkLocalInfoExpiry = 0
|
|
3055
3116
|
let tabLinkRouterInfoPromise = null
|
|
3056
3117
|
let tabLinkRouterInfoExpiry = 0
|
|
3118
|
+
let tabLinkRouterHttpsActive = null
|
|
3057
3119
|
|
|
3058
3120
|
const ensureTabLinkPopoverEl = () => {
|
|
3059
3121
|
if (!tabLinkPopoverEl) {
|
|
@@ -3078,7 +3140,12 @@ body.dark {
|
|
|
3078
3140
|
event.stopPropagation()
|
|
3079
3141
|
const url = item.getAttribute("data-url")
|
|
3080
3142
|
if (url) {
|
|
3081
|
-
|
|
3143
|
+
const targetMode = (item.getAttribute("data-target") || "_blank").toLowerCase()
|
|
3144
|
+
if (targetMode === "_self") {
|
|
3145
|
+
window.location.assign(url)
|
|
3146
|
+
} else {
|
|
3147
|
+
window.open(url, "_blank", "noopener")
|
|
3148
|
+
}
|
|
3082
3149
|
}
|
|
3083
3150
|
hideTabLinkPopover({ immediate: true })
|
|
3084
3151
|
})
|
|
@@ -3395,6 +3462,9 @@ body.dark {
|
|
|
3395
3462
|
return response.json()
|
|
3396
3463
|
})
|
|
3397
3464
|
.then((data) => {
|
|
3465
|
+
if (typeof data?.https_active === "boolean") {
|
|
3466
|
+
tabLinkRouterHttpsActive = data.https_active
|
|
3467
|
+
}
|
|
3398
3468
|
const processes = Array.isArray(data?.router_info) ? data.router_info : []
|
|
3399
3469
|
const rewriteMapping = data?.rewrite_mapping && typeof data.rewrite_mapping === "object"
|
|
3400
3470
|
? Object.values(data.rewrite_mapping)
|
|
@@ -3628,10 +3698,13 @@ body.dark {
|
|
|
3628
3698
|
hostPortMap
|
|
3629
3699
|
}
|
|
3630
3700
|
})
|
|
3631
|
-
.catch(() =>
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3701
|
+
.catch(() => {
|
|
3702
|
+
tabLinkRouterHttpsActive = null
|
|
3703
|
+
return {
|
|
3704
|
+
portMap: new Map(),
|
|
3705
|
+
hostPortMap: new Map()
|
|
3706
|
+
}
|
|
3707
|
+
})
|
|
3635
3708
|
tabLinkRouterInfoExpiry = now + 3000
|
|
3636
3709
|
}
|
|
3637
3710
|
return tabLinkRouterInfoPromise
|
|
@@ -3991,6 +4064,8 @@ body.dark {
|
|
|
3991
4064
|
header.innerHTML = `<i class="fa-solid fa-arrow-up-right-from-square"></i><span>Open in browser</span>`
|
|
3992
4065
|
popover.appendChild(header)
|
|
3993
4066
|
|
|
4067
|
+
const hasHttpsEntry = entries.some((entry) => entry && entry.type === "https")
|
|
4068
|
+
|
|
3994
4069
|
entries.forEach((entry) => {
|
|
3995
4070
|
const item = document.createElement("button")
|
|
3996
4071
|
item.type = "button"
|
|
@@ -4006,6 +4081,26 @@ body.dark {
|
|
|
4006
4081
|
popover.appendChild(item)
|
|
4007
4082
|
})
|
|
4008
4083
|
|
|
4084
|
+
if (tabLinkRouterHttpsActive === false && !hasHttpsEntry) {
|
|
4085
|
+
const footerButton = document.createElement("button")
|
|
4086
|
+
footerButton.type = "button"
|
|
4087
|
+
footerButton.className = "tab-link-popover-item tab-link-popover-footer"
|
|
4088
|
+
footerButton.setAttribute("data-url", "/network")
|
|
4089
|
+
footerButton.setAttribute("data-target", "_self")
|
|
4090
|
+
footerButton.setAttribute("aria-label", "Open network settings to configure local HTTPS")
|
|
4091
|
+
|
|
4092
|
+
const footerLabel = document.createElement("span")
|
|
4093
|
+
footerLabel.className = "label"
|
|
4094
|
+
footerLabel.textContent = "Custom domain not active"
|
|
4095
|
+
|
|
4096
|
+
const footerValue = document.createElement("span")
|
|
4097
|
+
footerValue.className = "value"
|
|
4098
|
+
footerValue.textContent = "Click to activate"
|
|
4099
|
+
|
|
4100
|
+
footerButton.append(footerLabel, footerValue)
|
|
4101
|
+
popover.appendChild(footerButton)
|
|
4102
|
+
}
|
|
4103
|
+
|
|
4009
4104
|
tabLinkActiveLink = link
|
|
4010
4105
|
tabLinkPendingLink = null
|
|
4011
4106
|
positionTabLinkPopover(popover, link)
|
|
@@ -4160,6 +4255,13 @@ body.dark {
|
|
|
4160
4255
|
})(),
|
|
4161
4256
|
target: node.getAttribute('target') || null,
|
|
4162
4257
|
dataIndex: node.getAttribute('data-index') || null,
|
|
4258
|
+
pagePath: (() => {
|
|
4259
|
+
try {
|
|
4260
|
+
return window.location?.pathname || null
|
|
4261
|
+
} catch (_) {
|
|
4262
|
+
return null
|
|
4263
|
+
}
|
|
4264
|
+
})()
|
|
4163
4265
|
}
|
|
4164
4266
|
try {
|
|
4165
4267
|
const key = selectionStorageKey()
|
|
@@ -4173,24 +4275,41 @@ body.dark {
|
|
|
4173
4275
|
})
|
|
4174
4276
|
} catch (_) {}
|
|
4175
4277
|
}
|
|
4176
|
-
const restorePersistedFrameLink = () => {
|
|
4278
|
+
const restorePersistedFrameLink = (providedPayload = null) => {
|
|
4177
4279
|
const storage = getWindowStorage()
|
|
4178
|
-
if (!storage) {
|
|
4179
|
-
return null
|
|
4180
|
-
}
|
|
4181
4280
|
const key = selectionStorageKey()
|
|
4182
|
-
|
|
4183
|
-
|
|
4281
|
+
const currentPath = (() => {
|
|
4282
|
+
try {
|
|
4283
|
+
return window.location?.pathname || ""
|
|
4284
|
+
} catch (_) {
|
|
4285
|
+
return ""
|
|
4286
|
+
}
|
|
4287
|
+
})()
|
|
4288
|
+
let payload = providedPayload
|
|
4289
|
+
if (!payload) {
|
|
4290
|
+
if (!storage || !key) {
|
|
4291
|
+
return null
|
|
4292
|
+
}
|
|
4293
|
+
const raw = storage.getItem(key)
|
|
4294
|
+
if (!raw) {
|
|
4295
|
+
return null
|
|
4296
|
+
}
|
|
4297
|
+
try {
|
|
4298
|
+
payload = JSON.parse(raw)
|
|
4299
|
+
} catch (_) {
|
|
4300
|
+
payload = { selector: raw }
|
|
4301
|
+
}
|
|
4184
4302
|
}
|
|
4185
|
-
|
|
4186
|
-
if (!raw) {
|
|
4303
|
+
if (!payload) {
|
|
4187
4304
|
return null
|
|
4188
4305
|
}
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4306
|
+
if (typeof payload === 'object' && payload !== null && typeof payload.pagePath === 'string') {
|
|
4307
|
+
if (currentPath && payload.pagePath !== currentPath) {
|
|
4308
|
+
return null
|
|
4309
|
+
}
|
|
4310
|
+
}
|
|
4311
|
+
if (typeof payload === 'string') {
|
|
4312
|
+
payload = { selector: payload }
|
|
4194
4313
|
}
|
|
4195
4314
|
const trySelector = (selector) => {
|
|
4196
4315
|
if (!selector || typeof selector !== 'string') {
|
|
@@ -4849,14 +4968,48 @@ body.dark {
|
|
|
4849
4968
|
const renderSelection = async ({ event: eventParam = null, target: explicitTarget = null, force = false } = {}) => {
|
|
4850
4969
|
const storage = getWindowStorage()
|
|
4851
4970
|
const selectionKey = selectionStorageKey()
|
|
4852
|
-
const
|
|
4971
|
+
const currentPath = (() => {
|
|
4972
|
+
try {
|
|
4973
|
+
return window.location?.pathname || ""
|
|
4974
|
+
} catch (_) {
|
|
4975
|
+
return ""
|
|
4976
|
+
}
|
|
4977
|
+
})()
|
|
4853
4978
|
let persistedSelectionRaw = selectionKey && storage ? storage.getItem(selectionKey) : null
|
|
4979
|
+
const devRouteActive = /\/dev(?:$|\/)/.test(currentPath || "")
|
|
4980
|
+
let persistedSelectionPayload = null
|
|
4981
|
+
if (persistedSelectionRaw) {
|
|
4982
|
+
try {
|
|
4983
|
+
const parsed = JSON.parse(persistedSelectionRaw)
|
|
4984
|
+
if (parsed && typeof parsed === "object") {
|
|
4985
|
+
if (typeof parsed.pagePath === "string") {
|
|
4986
|
+
if (!currentPath || parsed.pagePath === currentPath) {
|
|
4987
|
+
persistedSelectionPayload = parsed
|
|
4988
|
+
}
|
|
4989
|
+
} else if (!devRouteActive) {
|
|
4990
|
+
persistedSelectionPayload = parsed
|
|
4991
|
+
}
|
|
4992
|
+
}
|
|
4993
|
+
} catch (_) {
|
|
4994
|
+
if (!devRouteActive) {
|
|
4995
|
+
persistedSelectionPayload = { selector: persistedSelectionRaw }
|
|
4996
|
+
}
|
|
4997
|
+
}
|
|
4998
|
+
}
|
|
4999
|
+
if (!persistedSelectionPayload) {
|
|
5000
|
+
persistedSelectionRaw = null
|
|
5001
|
+
}
|
|
5002
|
+
const originalHasPersistedSelection = Boolean(persistedSelectionPayload)
|
|
4854
5003
|
const skipPersistedSelection = ignorePersistedSelection
|
|
4855
5004
|
let hasPersistedSelection = skipPersistedSelection ? false : originalHasPersistedSelection
|
|
4856
5005
|
if (skipPersistedSelection) {
|
|
4857
5006
|
persistedSelectionRaw = null
|
|
5007
|
+
persistedSelectionPayload = null
|
|
4858
5008
|
}
|
|
4859
5009
|
|
|
5010
|
+
const triggeredByUser = Boolean(eventParam || explicitTarget)
|
|
5011
|
+
let resolvedByGlobalSelector = false
|
|
5012
|
+
|
|
4860
5013
|
let target = explicitTarget
|
|
4861
5014
|
let preselected = null
|
|
4862
5015
|
|
|
@@ -4869,22 +5022,22 @@ body.dark {
|
|
|
4869
5022
|
if (candidate) {
|
|
4870
5023
|
target = candidate
|
|
4871
5024
|
global_selector = null
|
|
5025
|
+
resolvedByGlobalSelector = true
|
|
4872
5026
|
} else {
|
|
4873
5027
|
scheduleSelectionRetry()
|
|
4874
5028
|
return
|
|
4875
5029
|
}
|
|
4876
5030
|
}
|
|
4877
5031
|
|
|
5032
|
+
console.log({ target, skipPersistedSelection })
|
|
4878
5033
|
if (!target && !skipPersistedSelection) {
|
|
4879
5034
|
preselected = document.querySelector('#devtab.frame-link.selected') || document.querySelector('.frame-link.selected')
|
|
4880
|
-
|
|
4881
|
-
target = preselected
|
|
4882
|
-
}
|
|
5035
|
+
console.log({ preselected })
|
|
4883
5036
|
}
|
|
4884
5037
|
|
|
4885
|
-
if (!target &&
|
|
4886
|
-
target = restorePersistedFrameLink()
|
|
4887
|
-
if (!target &&
|
|
5038
|
+
if (!target && persistedSelectionPayload) {
|
|
5039
|
+
target = restorePersistedFrameLink(persistedSelectionPayload)
|
|
5040
|
+
if (!target && originalHasPersistedSelection) {
|
|
4888
5041
|
scheduleSelectionRetry()
|
|
4889
5042
|
return
|
|
4890
5043
|
}
|
|
@@ -4898,11 +5051,18 @@ body.dark {
|
|
|
4898
5051
|
}
|
|
4899
5052
|
}
|
|
4900
5053
|
|
|
4901
|
-
|
|
5054
|
+
const devTab = document.querySelector('#devtab.frame-link')
|
|
5055
|
+
if (!triggeredByUser && !resolvedByGlobalSelector && !target && devRouteActive && devTab) {
|
|
5056
|
+
target = devTab
|
|
5057
|
+
} else if (!target && preselected) {
|
|
5058
|
+
target = preselected
|
|
5059
|
+
}
|
|
5060
|
+
|
|
5061
|
+
if (!target) {
|
|
4902
5062
|
const defaultSelection = document.querySelector("[data-default]")
|
|
4903
5063
|
if (defaultSelection) {
|
|
4904
5064
|
target = defaultSelection
|
|
4905
|
-
} else {
|
|
5065
|
+
} else if (skipPersistedSelection) {
|
|
4906
5066
|
scheduleSelectionRetry()
|
|
4907
5067
|
return
|
|
4908
5068
|
}
|
|
@@ -4939,6 +5099,12 @@ body.dark {
|
|
|
4939
5099
|
}
|
|
4940
5100
|
<% } %>
|
|
4941
5101
|
|
|
5102
|
+
if (!target && preselected) {
|
|
5103
|
+
target = preselected
|
|
5104
|
+
}
|
|
5105
|
+
|
|
5106
|
+
console.log({ targetAfter: target })
|
|
5107
|
+
|
|
4942
5108
|
if (!target) {
|
|
4943
5109
|
target = document.querySelector(".frame-link")
|
|
4944
5110
|
}
|
|
@@ -5239,7 +5405,7 @@ body.dark {
|
|
|
5239
5405
|
item.href = url
|
|
5240
5406
|
item.setAttribute("data-index", index)
|
|
5241
5407
|
item.className = "btn header-item frame-link"
|
|
5242
|
-
item.innerHTML = `<div class='tab'><i class="fa-solid fa-link"></i><div class='display'>${url}</div><div class='flexible'></div><button class='btn2 del'><i class="fa-solid fa-
|
|
5408
|
+
item.innerHTML = `<div class='tab'><i class="fa-solid fa-link"></i><div class='display'>${url}</div><div class='flexible'></div><button class='btn2 del'><i class="fa-solid fa-circle-stop"></i></button></div>`
|
|
5243
5409
|
|
|
5244
5410
|
document.querySelector(".temp-menu").appendChild(item)
|
|
5245
5411
|
|
|
@@ -5920,7 +6086,7 @@ body.dark {
|
|
|
5920
6086
|
})
|
|
5921
6087
|
setupTabLinkHover()
|
|
5922
6088
|
document.addEventListener("click", (event) => {
|
|
5923
|
-
if (event.target.closest("#fs-status .fs-dropdown-menu")) {
|
|
6089
|
+
if (event.target.closest("#fs-status .fs-dropdown-menu") || event.target.closest("#fs-status .fs-status-btn")) {
|
|
5924
6090
|
return
|
|
5925
6091
|
}
|
|
5926
6092
|
closeStatusDropdowns()
|
|
@@ -6409,6 +6575,7 @@ body.dark {
|
|
|
6409
6575
|
|
|
6410
6576
|
const detachHandlers = () => {
|
|
6411
6577
|
forkBtn.removeEventListener('click', handlePushLogin)
|
|
6578
|
+
forkBtn.removeEventListener('click', requireGitLogin)
|
|
6412
6579
|
}
|
|
6413
6580
|
|
|
6414
6581
|
const enableDropdown = () => {
|
|
@@ -6419,7 +6586,11 @@ body.dark {
|
|
|
6419
6586
|
const disableDropdown = () => {
|
|
6420
6587
|
forkBtn.classList.remove('revealer')
|
|
6421
6588
|
forkBtn.removeAttribute('data-group')
|
|
6422
|
-
|
|
6589
|
+
const forkMenuEl = document.querySelector('#fs-fork-menu')
|
|
6590
|
+
if (forkMenuEl && !forkMenuEl.classList.contains('hidden')) {
|
|
6591
|
+
forkMenuEl.classList.add('hidden')
|
|
6592
|
+
}
|
|
6593
|
+
setDropdownState(forkBtn, false)
|
|
6423
6594
|
}
|
|
6424
6595
|
|
|
6425
6596
|
detachHandlers()
|
|
@@ -6435,12 +6606,12 @@ body.dark {
|
|
|
6435
6606
|
if (!isConnected) {
|
|
6436
6607
|
disableDropdown()
|
|
6437
6608
|
if (labelEl) {
|
|
6438
|
-
labelEl.textContent = '
|
|
6609
|
+
labelEl.textContent = 'Fork'
|
|
6439
6610
|
}
|
|
6440
6611
|
forkBtn.disabled = false
|
|
6441
6612
|
forkBtn.classList.remove('fs-status-btn--disabled')
|
|
6442
|
-
forkBtn.setAttribute('title', '
|
|
6443
|
-
forkBtn.addEventListener('click',
|
|
6613
|
+
forkBtn.setAttribute('title', 'Log in to GitHub to fork this workspace')
|
|
6614
|
+
forkBtn.addEventListener('click', requireGitLogin)
|
|
6444
6615
|
return
|
|
6445
6616
|
}
|
|
6446
6617
|
|
|
@@ -8148,6 +8319,41 @@ body.dark {
|
|
|
8148
8319
|
function handlePushLogin() {
|
|
8149
8320
|
window.location.href = '/github'
|
|
8150
8321
|
}
|
|
8322
|
+
const promptGitLogin = () => {
|
|
8323
|
+
Swal.fire({
|
|
8324
|
+
html: `
|
|
8325
|
+
<div class="pinokio-github-login">
|
|
8326
|
+
<div class="pinokio-github-login__icon"><i class="fa-brands fa-github"></i></div>
|
|
8327
|
+
<div class="pinokio-github-login__title">Log in to GitHub</div>
|
|
8328
|
+
<div class="pinokio-github-login__body">Connect your GitHub account to fork or publish this workspace.</div>
|
|
8329
|
+
</div>
|
|
8330
|
+
`,
|
|
8331
|
+
showCancelButton: true,
|
|
8332
|
+
confirmButtonText: 'Log in',
|
|
8333
|
+
cancelButtonText: 'Not now',
|
|
8334
|
+
reverseButtons: true,
|
|
8335
|
+
showCloseButton: true,
|
|
8336
|
+
focusConfirm: true,
|
|
8337
|
+
customClass: {
|
|
8338
|
+
popup: 'pinokio-modern-modal pinokio-github-login-modal',
|
|
8339
|
+
htmlContainer: 'pinokio-modern-html',
|
|
8340
|
+
confirmButton: 'pinokio-modern-confirm',
|
|
8341
|
+
cancelButton: 'pinokio-modern-cancel',
|
|
8342
|
+
closeButton: 'pinokio-modern-close'
|
|
8343
|
+
}
|
|
8344
|
+
}).then((result) => {
|
|
8345
|
+
if (result.isConfirmed) {
|
|
8346
|
+
handlePushLogin()
|
|
8347
|
+
}
|
|
8348
|
+
})
|
|
8349
|
+
}
|
|
8350
|
+
const requireGitLogin = (event) => {
|
|
8351
|
+
if (event) {
|
|
8352
|
+
event.preventDefault()
|
|
8353
|
+
event.stopPropagation()
|
|
8354
|
+
}
|
|
8355
|
+
promptGitLogin()
|
|
8356
|
+
}
|
|
8151
8357
|
|
|
8152
8358
|
// Function to update publish/create button
|
|
8153
8359
|
const updatePublishButton = async () => {
|
|
@@ -8167,6 +8373,7 @@ body.dark {
|
|
|
8167
8373
|
pushBtn.removeEventListener('click', showPublishModal)
|
|
8168
8374
|
pushBtn.removeEventListener('click', showCreateModal)
|
|
8169
8375
|
pushBtn.removeEventListener('click', handlePushLogin)
|
|
8376
|
+
pushBtn.removeEventListener('click', requireGitLogin)
|
|
8170
8377
|
}
|
|
8171
8378
|
const enableDropdown = () => {
|
|
8172
8379
|
pushBtn.classList.add('revealer')
|
|
@@ -8175,7 +8382,11 @@ body.dark {
|
|
|
8175
8382
|
const disableDropdown = () => {
|
|
8176
8383
|
pushBtn.classList.remove('revealer')
|
|
8177
8384
|
pushBtn.removeAttribute('data-group')
|
|
8178
|
-
|
|
8385
|
+
const pushMenuEl = document.querySelector('#fs-push-menu')
|
|
8386
|
+
if (pushMenuEl && !pushMenuEl.classList.contains('hidden')) {
|
|
8387
|
+
pushMenuEl.classList.add('hidden')
|
|
8388
|
+
}
|
|
8389
|
+
setDropdownState(pushBtn, false)
|
|
8179
8390
|
}
|
|
8180
8391
|
|
|
8181
8392
|
const repos = getRepoListSnapshot()
|
|
@@ -8227,12 +8438,12 @@ body.dark {
|
|
|
8227
8438
|
renderPublishDropdown(repos, { emptyMessage })
|
|
8228
8439
|
|
|
8229
8440
|
if (!isConnected) {
|
|
8230
|
-
setLabel('
|
|
8441
|
+
setLabel('Publish')
|
|
8231
8442
|
pushBtn.disabled = false
|
|
8232
8443
|
pushBtn.classList.remove('fs-status-btn--disabled')
|
|
8233
|
-
pushBtn.setAttribute('title', '
|
|
8444
|
+
pushBtn.setAttribute('title', 'Log in to GitHub to publish this workspace')
|
|
8234
8445
|
disableDropdown()
|
|
8235
|
-
pushBtn.addEventListener('click',
|
|
8446
|
+
pushBtn.addEventListener('click', requireGitLogin)
|
|
8236
8447
|
syncForkButton()
|
|
8237
8448
|
return
|
|
8238
8449
|
}
|
|
@@ -8266,12 +8477,12 @@ body.dark {
|
|
|
8266
8477
|
} catch (error) {
|
|
8267
8478
|
console.error('Error checking remotes:', error)
|
|
8268
8479
|
setPublishMenuMessage('Git integration unavailable')
|
|
8269
|
-
setLabel('
|
|
8480
|
+
setLabel('Publish')
|
|
8270
8481
|
pushBtn.disabled = false
|
|
8271
8482
|
pushBtn.classList.remove('fs-status-btn--disabled')
|
|
8272
|
-
pushBtn.setAttribute('title', '
|
|
8483
|
+
pushBtn.setAttribute('title', 'Log in to GitHub to publish this workspace')
|
|
8273
8484
|
disableDropdown()
|
|
8274
|
-
pushBtn.addEventListener('click',
|
|
8485
|
+
pushBtn.addEventListener('click', requireGitLogin)
|
|
8275
8486
|
latestGitIntegration = null
|
|
8276
8487
|
updateForkButton()
|
|
8277
8488
|
}
|
|
@@ -202,7 +202,7 @@ body.dark .browser-options-row {
|
|
|
202
202
|
<% if (dep.downloaded) { %>
|
|
203
203
|
<div class='item'><i class="fa-solid fa-check"></i> <a class='downloaded' href="<%=dep.downloaded%>" target="_blank"><%=dep.uri%></a><div class='flexible'></div></div>
|
|
204
204
|
<% } else { %>
|
|
205
|
-
<div class='item'><a class='btn' href="
|
|
205
|
+
<div class='item'><a class='btn' href="/?mode=download&uri=<%= encodeURIComponent(dep.uri) %>" target="_blank"><i class="fa-solid fa-download"></i> Download</a> <%=dep.uri%><div class='flexible'></div></div>
|
|
206
206
|
<% } %>
|
|
207
207
|
<% }) %>
|
|
208
208
|
</div>
|
package/server/views/index.ejs
CHANGED
|
@@ -464,7 +464,7 @@ body.dark aside .current.selected {
|
|
|
464
464
|
<% if (dep.downloaded) { %>
|
|
465
465
|
<div class='item'><i class="fa-solid fa-check"></i> <a class='downloaded' href="<%=dep.downloaded%>" target="_blank"><%=dep.uri%></a><div class='flexible'></div></div>
|
|
466
466
|
<% } else { %>
|
|
467
|
-
<div class='item'><a class='btn' href="
|
|
467
|
+
<div class='item'><a class='btn' href="/?mode=download&uri=<%= encodeURIComponent(dep.uri) %>" target="_blank"><i class="fa-solid fa-download"></i> Download</a> <%=dep.uri%><div class='flexible'></div></div>
|
|
468
468
|
<% } %>
|
|
469
469
|
<% }) %>
|
|
470
470
|
</div>
|
package/server/views/index2.ejs
CHANGED
|
@@ -290,7 +290,7 @@ body.dark .open-menu, body.dark .browse {
|
|
|
290
290
|
<% if (dep.downloaded) { %>
|
|
291
291
|
<div class='item'><i class="fa-solid fa-check"></i> <a class='downloaded' href="<%=dep.downloaded%>" target="_blank"><%=dep.uri%></a><div class='flexible'></div></div>
|
|
292
292
|
<% } else { %>
|
|
293
|
-
<div class='item'><a class='btn' href="
|
|
293
|
+
<div class='item'><a class='btn' href="/?mode=download&uri=<%= encodeURIComponent(dep.uri) %>" target="_blank"><i class="fa-solid fa-download"></i> Download</a> <%=dep.uri%><div class='flexible'></div></div>
|
|
294
294
|
<% } %>
|
|
295
295
|
<% }) %>
|
|
296
296
|
</div>
|