pinokiod 8.2.34 → 8.2.35

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": "8.2.34",
3
+ "version": "8.2.35",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -38,31 +38,15 @@ body.dark .anywhere-card { border-color: rgba(255,255,255,0.1); background: rgba
38
38
  .anywhere-card h3 { margin: 18px 0 6px; font-size: 13px; text-transform: uppercase; letter-spacing: 0.04em; opacity: 0.7; }
39
39
  .anywhere-card p { margin: 6px 0; line-height: 1.5; }
40
40
  .anywhere-muted { opacity: 0.7; font-size: 13px; }
41
- .anywhere-grid { display: grid; grid-template-columns: minmax(280px, 380px) 1fr; gap: 16px; align-items: start; }
42
- @media (max-width: 900px) { .anywhere-grid { grid-template-columns: 1fr; } }
43
- .anywhere-signout { background: none; border: none; padding: 0; font: inherit; color: inherit; text-decoration: underline; cursor: pointer; }
44
- /* which device is connecting: a segmented control, the phone panel by default */
45
- .anywhere-segments { display: grid; grid-template-columns: 1fr 1fr; width: 100%; padding: 4px; border-radius: 12px; background: rgba(0,0,0,0.05); }
46
- body.dark .anywhere-segments { background: rgba(255,255,255,0.08); }
47
- .anywhere-segments label { position: relative; display: block; }
48
- .anywhere-segments input { position: absolute; opacity: 0; width: 0; height: 0; }
49
- .anywhere-segments span { display: block; text-align: center; padding: 9px 12px; border-radius: 9px; font-size: 14px; cursor: pointer; opacity: 0.7; transition: opacity 0.15s; }
50
- .anywhere-segments span:hover { opacity: 1; }
51
- .anywhere-segments input:checked + span { background: white; font-weight: bold; opacity: 1; box-shadow: 0 1px 3px rgba(0,0,0,0.12); }
52
- body.dark .anywhere-segments input:checked + span { background: rgba(255,255,255,0.16); box-shadow: none; }
53
- .anywhere-segments input:focus-visible + span { outline: 2px solid currentColor; outline-offset: 1px; }
54
- #anywhere-connect[data-device=phone] [data-panel=computer], #anywhere-connect[data-device=computer] [data-panel=phone] { display: none; }
55
- #anywhere-connect [data-panel] { display: flex; flex-direction: column; align-items: center; gap: 14px; width: 100%; }
56
- #anywhere-connect [data-panel] p { margin: 0; max-width: 360px; font-size: 15px; line-height: 1.5; }
57
- #anywhere-connect [data-panel=computer] { padding-top: 10px; }
58
- .anywhere-warning { padding: 10px 14px; border-radius: 8px; background: rgba(255,140,0,0.14); font-size: 13px; line-height: 1.5; margin: 16px 0 0; }
59
- .anywhere-warning a { color: inherit; }
60
- .anywhere-connect-card { max-width: 440px; padding: 22px 24px 24px; }
61
- .anywhere-connect-title { text-align: center; font-size: 17px; margin: 0 0 14px; }
62
- .anywhere-qr { display: flex; flex-direction: column; align-items: center; gap: 14px; text-align: center; }
63
- .anywhere-qr img { width: 212px; height: 212px; border-radius: 14px; background: white; padding: 12px; border: 1px solid rgba(0,0,0,0.08); margin-top: 4px; }
64
- body.dark .anywhere-qr img { border-color: transparent; }
65
- .anywhere-qr > .anywhere-muted { font-size: 12px; margin-top: 2px; }
41
+ .anywhere-connect { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: stretch; }
42
+ @media (max-width: 900px) { .anywhere-connect { grid-template-columns: 1fr; } }
43
+ .anywhere-device-card { display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 12px; text-align: center; padding: 22px 24px 24px; }
44
+ .anywhere-device-icon { font-size: 32px; line-height: 1; opacity: 0.7; margin-bottom: -2px; }
45
+ .anywhere-device-card h2 { font-size: 17px; margin: 0; }
46
+ .anywhere-device-card p { margin: 0; max-width: 360px; font-size: 15px; line-height: 1.5; }
47
+ .anywhere-device-card img { width: 212px; height: 212px; border-radius: 14px; background: white; padding: 12px; border: 1px solid rgba(0,0,0,0.08); }
48
+ body.dark .anywhere-device-card img { border-color: transparent; }
49
+ .anywhere-account-line { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; margin: 14px 0 18px; }
66
50
  .anywhere-address {
67
51
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
68
52
  font-size: 15px; word-break: break-all;
@@ -225,31 +209,29 @@ document.addEventListener('DOMContentLoaded', function() {
225
209
 
226
210
  <div class='anywhere-state' data-state='ready'>
227
211
  <div class='anywhere-warning' id='anywhere-expiry-warning' hidden></div>
228
- <div class='anywhere-grid'>
229
- <div class='anywhere-card anywhere-connect-card'>
230
- <h2 class='anywhere-connect-title'>Connect a device</h2>
231
- <div class='anywhere-qr' id='anywhere-connect' data-device='phone'>
232
- <div class='anywhere-segments'>
233
- <label><input type='radio' name='anywhere-device' value='phone' checked><span>Phone or tablet</span></label>
234
- <label><input type='radio' name='anywhere-device' value='computer'><span>Another computer</span></label>
235
- </div>
236
- <div data-panel='phone'>
237
- <img id='anywhere-qr' alt='QR code to connect' src=''>
238
- <p>Scan with your phone. It walks you through the rest.</p>
239
- </div>
240
- <div data-panel='computer'>
241
- <p>Open this link on the other computer. It walks you through installing Tailscale and signing in as <b class='anywhere-account-inline'></b>, then opens this Pinokio.</p>
242
- <div class='anywhere-address'><a id='anywhere-address' href='#' target='_blank' rel='noopener'></a></div>
243
- <p><button type='button' class='anywhere-btn secondary anywhere-copy' id='anywhere-copy' disabled><i class='fa-regular fa-copy' aria-hidden='true'></i> Copy link</button></p>
244
- <div id='anywhere-copy-status' class='anywhere-muted' role='status' aria-live='polite'></div>
245
- <div id='anywhere-copy-manual' class='anywhere-copy-manual' hidden>
246
- <input id='anywhere-copy-value' type='text' readonly aria-label='Remote link' aria-describedby='anywhere-copy-status'>
247
- </div>
248
- </div>
249
- <div class='anywhere-muted'>signed in as <b id='anywhere-account'></b> · <button type='button' class='anywhere-signout' data-action='logout'>Sign out</button></div>
250
- <div class='anywhere-waiting' id='anywhere-waiting'><i class="fa-solid fa-circle-notch fa-spin"></i> Waiting for another device to join…</div>
212
+ <div class='anywhere-connect' id='anywhere-connect'>
213
+ <div class='anywhere-card anywhere-device-card'>
214
+ <i class='fa-solid fa-mobile-screen anywhere-device-icon' aria-hidden='true'></i>
215
+ <h2>Connect a phone or tablet</h2>
216
+ <p>Scan with your phone. It walks you through the rest.</p>
217
+ <img id='anywhere-qr' alt='QR code to connect' src=''>
218
+ </div>
219
+ <div class='anywhere-card anywhere-device-card'>
220
+ <i class='fa-solid fa-laptop anywhere-device-icon' aria-hidden='true'></i>
221
+ <h2>Connect another computer</h2>
222
+ <p>Open this link on the other computer. It walks you through installing Tailscale and signing in as <b class='anywhere-account-inline'></b>, then opens this Pinokio.</p>
223
+ <div class='anywhere-address'><a id='anywhere-address' href='#' target='_blank' rel='noopener'></a></div>
224
+ <p><button type='button' class='anywhere-btn secondary anywhere-copy' id='anywhere-copy' disabled><i class='fa-regular fa-copy' aria-hidden='true'></i> Copy link</button></p>
225
+ <div id='anywhere-copy-status' class='anywhere-muted' role='status' aria-live='polite'></div>
226
+ <div id='anywhere-copy-manual' class='anywhere-copy-manual' hidden>
227
+ <input id='anywhere-copy-value' type='text' readonly aria-label='Remote link' aria-describedby='anywhere-copy-status'>
251
228
  </div>
252
229
  </div>
230
+ </div>
231
+ <div class='anywhere-account-line'>
232
+ <span class='anywhere-muted'>signed in as <b id='anywhere-account'></b> · <button type='button' class='anywhere-signout' data-action='logout'>Sign out</button></span>
233
+ <div class='anywhere-waiting' id='anywhere-waiting'><i class="fa-solid fa-circle-notch fa-spin"></i> Waiting for another device to join…</div>
234
+ </div>
253
235
  <div id='anywhere-details' hidden>
254
236
  <div class='anywhere-card'>
255
237
  <h2>Running apps</h2>
@@ -275,7 +257,6 @@ document.addEventListener('DOMContentLoaded', function() {
275
257
  </p>
276
258
  </div>
277
259
  </div>
278
- </div>
279
260
  </div>
280
261
 
281
262
  </div>
@@ -525,9 +506,6 @@ document.addEventListener('DOMContentLoaded', function() {
525
506
  openExternal(link.href)
526
507
  }
527
508
  })
528
- for (const input of document.querySelectorAll('input[name=anywhere-device]')) {
529
- input.addEventListener('change', () => { document.getElementById('anywhere-connect').dataset.device = input.value })
530
- }
531
509
  switchEl.addEventListener('click', () => {
532
510
  if (switchEl.dataset.on === 'true') {
533
511
  act('stop')
@@ -36,22 +36,24 @@ test('before any device joins, the ready state is the connect card alone, with s
36
36
  const h = render(t, { phase: 'ready', peers: [] })
37
37
  const card = h.document.querySelector('[data-state=ready] .anywhere-card')
38
38
  assert.equal(h.document.getElementById('anywhere-details').hidden, true, 'apps, devices and details wait for a device')
39
- assert.ok(card.querySelector('.anywhere-signout[data-action=logout]'), 'a wrong-account sign-in is fixable during onboarding')
39
+ assert.ok(h.document.querySelector('.anywhere-account-line .anywhere-signout[data-action=logout]'), 'a wrong-account sign-in is fixable during onboarding')
40
40
  assert.ok(!h.document.querySelector('#anywhere-details [data-action=logout]'), 'sign out lives with the account, not in details')
41
41
  assert.equal(card.querySelectorAll('ol, h3').length, 0, 'no step lists on the desk: the phone page explains Tailscale after the scan')
42
42
  const connect = h.document.getElementById('anywhere-connect')
43
- assert.equal(connect.dataset.device, 'phone', 'the QR is the default')
44
- assert.match(connect.querySelector('[data-panel=phone]').textContent, /Scan with your phone\./)
45
- const computer = connect.querySelector('[data-panel=computer]')
46
- assert.match(computer.textContent, /signing in as me@example.com/)
47
- const choose = connect.querySelector('input[value=computer]')
48
- choose.checked = true
49
- choose.dispatchEvent(new h.document.defaultView.Event('change'))
50
- assert.equal(connect.dataset.device, 'computer', 'the segmented control switches the panel')
51
- const link = computer.querySelector('#anywhere-address')
52
- assert.equal(link.getAttribute('href'), connectUrl, 'the computer path is the same link the QR carries')
53
- assert.equal(link.textContent, 'pinokio.co/anywhere/connect#…', 'the fragment is not spelled out')
54
- assert.equal(h.text('anywhere-account'), 'me@example.com')
43
+ const cards = connect.querySelectorAll('.anywhere-device-card')
44
+ assert.equal(cards.length, 2, 'both ways in, side by side, nothing behind a toggle')
45
+ for (const card of cards) {
46
+ const icon = card.querySelector('.anywhere-device-icon')
47
+ assert.ok(icon, 'each card leads with its own icon row')
48
+ assert.strictEqual(icon.nextElementSibling.tagName, 'H2')
49
+ }
50
+ assert.match(cards[0].textContent, /Connect a phone or tablet.*Scan with your phone\./s)
51
+ assert.ok(cards[0].querySelector('#anywhere-qr'))
52
+ assert.match(cards[1].textContent, /Connect another computer.*installing Tailscale and signing in as me@example\.com/s)
53
+ const link = cards[1].querySelector('#anywhere-address')
54
+ assert.equal(link.getAttribute('href'), connectUrl, 'the same link the QR carries')
55
+ assert.equal(link.textContent, 'pinokio.co/anywhere/connect#…')
56
+ assert.equal(h.document.querySelector('.anywhere-segments'), null)
55
57
  assert.match(h.text('anywhere-waiting'), /Waiting for another device/)
56
58
  assert.equal(h.document.getElementById('anywhere-expiry-warning').hidden, true)
57
59
  })