pinokiod 5.3.18 → 5.3.20

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinokiod",
3
- "version": "5.3.18",
3
+ "version": "5.3.20",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/server/index.js CHANGED
@@ -44,10 +44,6 @@ const DEFAULT_PORT = 42000
44
44
  const NOTIFICATION_SOUND_EXTENSIONS = new Set(['.aac', '.flac', '.m4a', '.mp3', '.ogg', '.wav', '.webm'])
45
45
  const LOG_STREAM_INITIAL_BYTES = 512 * 1024
46
46
  const LOG_STREAM_KEEPALIVE_MS = 25000
47
- const REGISTRY_PING_PNG = Buffer.from(
48
- 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMBAAObF+6bAAAAAElFTkSuQmCC',
49
- 'base64'
50
- )
51
47
  const DEFAULT_REGISTRY_URL = 'https://beta.pinokio.co'
52
48
 
53
49
  const ex = fn => (req, res, next) => {
@@ -1032,6 +1028,25 @@ class Server {
1032
1028
  let review_tab = "/p/" + name + "/review"
1033
1029
  let files_tab = "/p/" + name + "/files"
1034
1030
 
1031
+ const registryEnabled = await this.isRegistryEnabled().catch(() => false)
1032
+ let community_url = ""
1033
+ if (registryEnabled) {
1034
+ try {
1035
+ const repositoryPath = path.resolve(this.kernel.api.userdir, name)
1036
+ const gitRemote = await git.getConfig({
1037
+ fs,
1038
+ http,
1039
+ dir: repositoryPath,
1040
+ path: 'remote.origin.url'
1041
+ })
1042
+ if (gitRemote && this.portal) {
1043
+ community_url = `${this.portal}/resolve?url=${encodeURIComponent(gitRemote)}&embed=1`
1044
+ }
1045
+ } catch (_) {
1046
+ community_url = ""
1047
+ }
1048
+ }
1049
+
1035
1050
  let editor_tab = `/pinokio/fileview/${encodeURIComponent(name)}`
1036
1051
  let savedTabs = []
1037
1052
  if (Array.isArray(this.tabs[name])) {
@@ -1088,6 +1103,7 @@ class Server {
1088
1103
  dev_tab,
1089
1104
  review_tab,
1090
1105
  files_tab,
1106
+ community_url,
1091
1107
  // paths,
1092
1108
  theme: this.theme,
1093
1109
  agent: req.agent,
@@ -1107,7 +1123,6 @@ class Server {
1107
1123
  result.snapshotFooterEnabled = !!(options && options.snapshotFooterEnabled)
1108
1124
  result.hasSnapshots = !!(options && options.hasSnapshots)
1109
1125
  result.pendingSnapshotId = options && options.pendingSnapshotId ? String(options.pendingSnapshotId) : null
1110
- const registryEnabled = await this.isRegistryEnabled().catch(() => false)
1111
1126
  result.registryEnabled = registryEnabled
1112
1127
  if (!registryEnabled) {
1113
1128
  result.pendingSnapshotId = null
@@ -4758,15 +4773,6 @@ class Server {
4758
4773
  this.app.post("/checkpoints/registry", ex(async (req, res) => {
4759
4774
  res.status(404).json({ ok: false, error: "Not found" })
4760
4775
  }))
4761
- const registryPingHandler = ex(async (_req, res) => {
4762
- res.setHeader('Content-Type', 'image/png')
4763
- res.setHeader('Cache-Control', 'no-store')
4764
- res.setHeader('Content-Length', String(REGISTRY_PING_PNG.length))
4765
- res.end(REGISTRY_PING_PNG)
4766
- })
4767
- this.app.get("/registry/healthz.png", registryPingHandler)
4768
- this.app.get("/registry/ping.png", registryPingHandler)
4769
-
4770
4776
  this.app.get("/registry/checkin", ex(async (req, res) => {
4771
4777
  const repoUrl = typeof req.query.repo === 'string' ? req.query.repo.trim() : ''
4772
4778
  const returnRaw = typeof req.query.return === 'string' ? req.query.return.trim() : ''
@@ -140,8 +140,9 @@ if (onfinish) {
140
140
  }
141
141
  // The original task
142
142
  */
143
- function wait_ready (targetUrl = null) {
143
+ function wait_ready (targetUrl = null, options = {}) {
144
144
  createLauncherDebugLog('wait_ready invoked');
145
+ const showLoader = !(options && options.showLoader === false);
145
146
  let navTarget = null;
146
147
  if (targetUrl) {
147
148
  try {
@@ -159,6 +160,7 @@ function wait_ready (targetUrl = null) {
159
160
  createLauncherDebugLog('wait_ready initial requirements readiness', ready);
160
161
  let loader = null;
161
162
  const ensureLoader = () => {
163
+ if (!showLoader) return null;
162
164
  if (!loader) {
163
165
  loader = createMinimalLoadingSwal();
164
166
  }
@@ -172,7 +174,7 @@ function wait_ready (targetUrl = null) {
172
174
  };
173
175
  if (ready) {
174
176
  const initialLoader = pinokioDevGuardSatisfied ? null : ensureLoader();
175
- ensureDevReady(initialLoader, 'initial').then(finalize)
177
+ ensureDevReady(initialLoader, 'initial', undefined, showLoader).then(finalize)
176
178
  } else {
177
179
  ensureLoader();
178
180
  let interval = setInterval(() => {
@@ -180,7 +182,7 @@ function wait_ready (targetUrl = null) {
180
182
  createLauncherDebugLog('wait_ready polling requirements readiness', ready);
181
183
  if (ready) {
182
184
  clearInterval(interval)
183
- ensureDevReady(loader, 'after poll').then(finalize)
185
+ ensureDevReady(loader, 'after poll', undefined, showLoader).then(finalize)
184
186
  }
185
187
  })
186
188
  }, 500)
@@ -189,9 +191,10 @@ function wait_ready (targetUrl = null) {
189
191
  })
190
192
  }
191
193
 
192
- function ensureDevReady(existingLoader = null, label = 'initial', maxWaitMs = 15000) {
194
+ function ensureDevReady(existingLoader = null, label = 'initial', maxWaitMs = 15000, showLoader = true) {
193
195
  let loader = existingLoader;
194
196
  const ensureLoader = () => {
197
+ if (!showLoader) return null;
195
198
  if (!loader) {
196
199
  loader = createMinimalLoadingSwal();
197
200
  }
@@ -2689,17 +2692,43 @@ if (typeof window !== 'undefined' && !window.__pinokioNavigateListenerInstalled)
2689
2692
  try {
2690
2693
  console.info('[pinokio:navigate] received', { origin: event.origin, url: event.data?.url });
2691
2694
  } catch (_) {}
2692
- const frame = document.activeElement;
2693
- if (!frame || frame.tagName !== 'IFRAME') {
2695
+ const rawUrl = typeof event.data.url === 'string' ? event.data.url : '';
2696
+ if (!rawUrl) {
2694
2697
  try {
2695
- console.warn('[pinokio:navigate] no active iframe');
2698
+ console.warn('[pinokio:navigate] empty url');
2696
2699
  } catch (_) {}
2697
2700
  return;
2698
2701
  }
2699
- const rawUrl = typeof event.data.url === 'string' ? event.data.url : '';
2700
- if (!rawUrl) {
2702
+ const communityFrame = document.querySelector('iframe.community-frame');
2703
+ if (communityFrame) {
2704
+ let fromCommunity = false;
2701
2705
  try {
2702
- console.warn('[pinokio:navigate] empty url');
2706
+ fromCommunity = event.source === communityFrame.contentWindow;
2707
+ } catch (_) {
2708
+ fromCommunity = false;
2709
+ }
2710
+ if (fromCommunity) {
2711
+ let communityTarget;
2712
+ try {
2713
+ const base = communityFrame.getAttribute('src') || window.location.origin;
2714
+ communityTarget = new URL(rawUrl, base);
2715
+ } catch (_) {
2716
+ try {
2717
+ console.warn('[pinokio:navigate] invalid url', rawUrl);
2718
+ } catch (_) {}
2719
+ return;
2720
+ }
2721
+ communityFrame.src = communityTarget.toString();
2722
+ try {
2723
+ console.info('[pinokio:navigate] navigated community', communityFrame.src);
2724
+ } catch (_) {}
2725
+ return;
2726
+ }
2727
+ }
2728
+ const frame = document.activeElement;
2729
+ if (!frame || frame.tagName !== 'IFRAME') {
2730
+ try {
2731
+ console.warn('[pinokio:navigate] no active iframe');
2703
2732
  } catch (_) {}
2704
2733
  return;
2705
2734
  }
@@ -3401,6 +3430,7 @@ document.addEventListener("DOMContentLoaded", () => {
3401
3430
  }
3402
3431
  initCreateLauncherTrigger(api);
3403
3432
  initAskAiTrigger(api);
3433
+ warmCreateLauncherModal(api);
3404
3434
  openPendingCreateLauncherModal(api);
3405
3435
  });
3406
3436
  }
@@ -3436,6 +3466,20 @@ document.addEventListener("DOMContentLoaded", () => {
3436
3466
  return createLauncherState.loaderPromise;
3437
3467
  }
3438
3468
 
3469
+ function warmCreateLauncherModal(api) {
3470
+ if (!api || typeof api.ensureModalReady !== 'function') {
3471
+ return;
3472
+ }
3473
+ const runWarmup = () => {
3474
+ try {
3475
+ api.ensureModalReady();
3476
+ } catch (error) {
3477
+ createLauncherDebugLog('ensureModalReady failed', error);
3478
+ }
3479
+ };
3480
+ setTimeout(runWarmup, 0);
3481
+ }
3482
+
3439
3483
  function initCreateLauncherTrigger(api) {
3440
3484
  const trigger = document.getElementById('create-launcher-button');
3441
3485
  if (!trigger) {
@@ -3558,23 +3602,22 @@ document.addEventListener("DOMContentLoaded", () => {
3558
3602
  return;
3559
3603
  }
3560
3604
  createLauncherDebugLog('guardCreateLauncher invoked', { defaults: Boolean(defaults) });
3561
- wait_ready().then(({ closeModal, ready }) => {
3562
- createLauncherDebugLog('guardCreateLauncher wait_ready resolved', { ready, closeModal: Boolean(closeModal) });
3605
+ if (defaults) {
3606
+ api.showModal(defaults);
3607
+ } else {
3608
+ api.showModal();
3609
+ }
3610
+ wait_ready(null, { showLoader: false }).then(({ ready }) => {
3611
+ createLauncherDebugLog('guardCreateLauncher wait_ready resolved', { ready });
3563
3612
  if (ready) {
3564
- if (closeModal) {
3565
- closeModal()
3566
- }
3567
- createLauncherDebugLog('guardCreateLauncher proceeding to show modal', { defaults: Boolean(defaults) });
3568
- if (defaults) {
3569
- api.showModal(defaults);
3570
- } else {
3571
- api.showModal();
3572
- }
3573
- } else {
3574
- const callback = encodeURIComponent(window.location.pathname + window.location.search + window.location.hash);
3575
- createLauncherDebugLog('guardCreateLauncher redirecting to /setup/dev', { callback });
3576
- window.location.href = `/setup/dev?callback=${callback}`;
3613
+ return;
3614
+ }
3615
+ if (api && typeof api.hideModal === 'function') {
3616
+ api.hideModal();
3577
3617
  }
3618
+ const callback = encodeURIComponent(window.location.pathname + window.location.search + window.location.hash);
3619
+ createLauncherDebugLog('guardCreateLauncher redirecting to /setup/dev', { callback });
3620
+ window.location.href = `/setup/dev?callback=${callback}`;
3578
3621
  })
3579
3622
  }
3580
3623
 
@@ -47,6 +47,9 @@
47
47
  let modalInstance = null;
48
48
  let modalPromise = null;
49
49
  let modalKeydownHandler = null;
50
+ let modalOpen = false;
51
+ let modalPrevFocus = null;
52
+ let modalPrevInert = null;
50
53
 
51
54
  function mapPluginMenuToCreateLauncherTools(menu) {
52
55
  if (!Array.isArray(menu)) return [];
@@ -654,6 +657,43 @@
654
657
  };
655
658
  }
656
659
 
660
+ function setModalOpenState(open) {
661
+ const main = document.querySelector('main');
662
+ if (open) {
663
+ if (modalOpen) return;
664
+ modalOpen = true;
665
+ modalPrevFocus = document.activeElement;
666
+ if (main) {
667
+ modalPrevInert = main.hasAttribute('inert');
668
+ main.setAttribute('inert', '');
669
+ if (typeof main.inert !== 'undefined') {
670
+ main.inert = true;
671
+ }
672
+ }
673
+ try {
674
+ if (document.activeElement && typeof document.activeElement.blur === 'function') {
675
+ document.activeElement.blur();
676
+ }
677
+ } catch (_) {}
678
+ return;
679
+ }
680
+ if (!modalOpen) return;
681
+ modalOpen = false;
682
+ if (main && !modalPrevInert) {
683
+ if (typeof main.inert !== 'undefined') {
684
+ main.inert = false;
685
+ }
686
+ main.removeAttribute('inert');
687
+ }
688
+ modalPrevInert = null;
689
+ if (modalPrevFocus && typeof modalPrevFocus.focus === 'function') {
690
+ try {
691
+ modalPrevFocus.focus();
692
+ } catch (_) {}
693
+ }
694
+ modalPrevFocus = null;
695
+ }
696
+
657
697
  function applyVariantToUi(ui, variant = MODAL_VARIANTS.CREATE) {
658
698
  if (!ui) return;
659
699
  const targetVariant = variant === MODAL_VARIANTS.ASK ? MODAL_VARIANTS.ASK : MODAL_VARIANTS.CREATE;
@@ -902,15 +942,12 @@
902
942
  applyDefaultsToUi(ui, restDefaults);
903
943
  ui.templateManager.syncTemplateFields(ui.promptTextarea.value, restDefaults.templateValues || {});
904
944
 
905
- requestAnimationFrame(() => {
906
- ui.overlay.classList.add('is-visible');
907
- requestAnimationFrame(() => {
908
- if (ui.currentVariant !== MODAL_VARIANTS.ASK && ui.folderInput) {
909
- ui.folderInput.select();
910
- }
911
- ui.promptTextarea.focus();
912
- });
913
- });
945
+ setModalOpenState(true);
946
+ ui.overlay.classList.add('is-visible');
947
+ if (ui.currentVariant !== MODAL_VARIANTS.ASK && ui.folderInput) {
948
+ ui.folderInput.select();
949
+ }
950
+ ui.promptTextarea.focus();
914
951
 
915
952
  modalKeydownHandler = (event) => {
916
953
  if (event.key === 'Escape') {
@@ -928,6 +965,7 @@
928
965
  function hideModal() {
929
966
  if (!modalInstance) return;
930
967
  modalInstance.overlay.classList.remove('is-visible');
968
+ setModalOpenState(false);
931
969
  if (modalKeydownHandler) {
932
970
  document.removeEventListener('keydown', modalKeydownHandler, true);
933
971
  modalKeydownHandler = null;
@@ -94,6 +94,27 @@
94
94
  gap: 8px;
95
95
  }
96
96
 
97
+ .files-app__mobile-back {
98
+ display: none;
99
+ align-items: center;
100
+ gap: 6px;
101
+ padding: 6px 10px;
102
+ border-radius: 8px;
103
+ border: 1px solid var(--border-color);
104
+ background: var(--surface-color);
105
+ color: var(--text-color);
106
+ font-weight: 600;
107
+ cursor: pointer;
108
+ transition: background 0.15s ease, color 0.15s ease, transform 0.15s ease;
109
+ }
110
+
111
+ .files-app__mobile-back:hover,
112
+ .files-app__mobile-back:focus-visible {
113
+ background: var(--accent-color-soft);
114
+ color: var(--accent-color);
115
+ outline: none;
116
+ }
117
+
97
118
  .files-app__save {
98
119
  display: inline-flex;
99
120
  align-items: center;
@@ -363,6 +384,27 @@ body.dark .files-app__tab--stale .files-app__tab-label::after {
363
384
  transition: opacity 0.15s ease;
364
385
  }
365
386
 
387
+ .files-app__tree-more {
388
+ display: none;
389
+ align-items: center;
390
+ justify-content: center;
391
+ width: 28px;
392
+ height: 28px;
393
+ border-radius: 6px;
394
+ border: 1px solid transparent;
395
+ background: transparent;
396
+ color: var(--muted-color);
397
+ cursor: pointer;
398
+ transition: background 0.15s ease, color 0.15s ease;
399
+ }
400
+
401
+ .files-app__tree-more:hover,
402
+ .files-app__tree-more:focus-visible {
403
+ background: rgba(127, 91, 243, 0.15);
404
+ color: var(--text-color);
405
+ outline: none;
406
+ }
407
+
366
408
  .files-app__tree-row:hover,
367
409
  .files-app__tree-row:focus-visible {
368
410
  background: rgba(127, 91, 243, 0.12);
@@ -444,3 +486,87 @@ body.dark .files-app__tab--stale .files-app__tab-label::after {
444
486
  .files-app__status[data-state='success'] {
445
487
  color: #10b981;
446
488
  }
489
+
490
+ @media (max-width: 768px) {
491
+ .files-app {
492
+ height: 100dvh;
493
+ }
494
+
495
+ .files-app__header {
496
+ padding: 10px 14px;
497
+ gap: 10px;
498
+ }
499
+
500
+ .files-app__header-desc {
501
+ display: none;
502
+ }
503
+
504
+ .files-app__header-sub {
505
+ white-space: nowrap;
506
+ overflow: hidden;
507
+ text-overflow: ellipsis;
508
+ }
509
+
510
+ .files-app__header-actions {
511
+ gap: 6px;
512
+ }
513
+
514
+ .files-app__meta,
515
+ .files-app__save {
516
+ padding: 6px 10px;
517
+ }
518
+
519
+ .files-app__body {
520
+ flex-direction: column;
521
+ }
522
+
523
+ .files-app__sidebar {
524
+ width: 100%;
525
+ max-width: none;
526
+ border-right: none;
527
+ border-bottom: 1px solid var(--border-color);
528
+ }
529
+
530
+ .files-app__sidebar-scroll {
531
+ padding: 10px 0 16px;
532
+ }
533
+
534
+ .files-app__main {
535
+ width: 100%;
536
+ }
537
+
538
+ .files-app__sidebar-toggle {
539
+ display: none;
540
+ }
541
+
542
+ .files-app.files-app--mobile[data-mobile-view='editor'] .files-app__mobile-back {
543
+ display: inline-flex;
544
+ }
545
+
546
+ .files-app.files-app--mobile[data-mobile-view='list'] .files-app__mobile-back {
547
+ display: none;
548
+ }
549
+
550
+ .files-app.files-app--mobile[data-mobile-view='list'] .files-app__main {
551
+ display: none;
552
+ }
553
+
554
+ .files-app.files-app--mobile[data-mobile-view='editor'] .files-app__sidebar {
555
+ display: none;
556
+ }
557
+
558
+ .files-app__tree-actions {
559
+ display: none;
560
+ }
561
+
562
+ .files-app__tree-more {
563
+ display: inline-flex;
564
+ }
565
+ }
566
+
567
+ @media (max-width: 520px) {
568
+ .files-app__meta span,
569
+ .files-app__save span {
570
+ display: none;
571
+ }
572
+ }