signalk-race-control 0.4.0 → 0.4.1

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.
Files changed (2) hide show
  1. package/index.js +18 -4
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -377,13 +377,27 @@ function buildOfflineTimerHtml(race, defaultTcf, vetOptions) {
377
377
  // prematurely close the tag, e.g. via "</script>" in a boat name) is
378
378
  // escaped. JSON.parse doesn't need this reversed; < is valid JSON.
379
379
  const seedJson = JSON.stringify(seed).replace(/</g, '\\u003c');
380
+ // The race name also goes straight into HTML attributes/text below (page
381
+ // title, the iOS home-screen app title) — escaped the normal way for that
382
+ // context, distinct from the JSON escaping above.
383
+ const escapedRaceName = String(race.name || 'Race').replace(/[&<>"']/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]));
380
384
 
381
385
  return `<!doctype html>
382
386
  <html lang="en">
383
387
  <head>
384
388
  <meta charset="utf-8" />
385
- <meta name="viewport" content="width=device-width, initial-scale=1" />
386
- <title>Race Control — Offline Timer</title>
389
+ <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
390
+ <title>${escapedRaceName} — Offline Timer</title>
391
+ <meta name="theme-color" content="#0f172a" />
392
+ <!-- Lets "Add to Home Screen" on iOS launch this as a standalone app rather
393
+ than a Safari bookmark — standalone home-screen apps get their own
394
+ persistent storage that isn't subject to Safari's usual after-a-week
395
+ cleanup of unvisited sites, which is what actually makes the saved race
396
+ state stick around between uses. -->
397
+ <meta name="apple-mobile-web-app-capable" content="yes" />
398
+ <meta name="mobile-web-app-capable" content="yes" />
399
+ <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
400
+ <meta name="apple-mobile-web-app-title" content="${escapedRaceName}" />
387
401
  <style>
388
402
  :root {
389
403
  --bg: #0f172a; --panel: #1e293b; --border: #334155; --text: #e2e8f0;
@@ -392,7 +406,7 @@ function buildOfflineTimerHtml(race, defaultTcf, vetOptions) {
392
406
  * { box-sizing: border-box; }
393
407
  [hidden] { display: none !important; }
394
408
  body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; background: var(--bg); color: var(--text); }
395
- header { padding: 1.25rem 1.5rem; border-bottom: 1px solid var(--border); text-align: center; }
409
+ header { padding: max(1.25rem, env(safe-area-inset-top)) 1.5rem 1.25rem; border-bottom: 1px solid var(--border); text-align: center; }
396
410
  h1 { margin: 0 0 0.4rem; font-size: 1.1rem; font-weight: 600; letter-spacing: 0.02em; color: var(--muted); text-transform: uppercase; }
397
411
  h2 { margin: 0 0 0.75rem; font-size: 1.3rem; }
398
412
  .offline-note { max-width: 40rem; margin: 0 auto 1rem; font-size: 0.8rem; color: var(--muted); }
@@ -411,7 +425,7 @@ button.confirming { background: var(--bad); color: #2a0a0a; border-color: var(--
411
425
  button:disabled { opacity: 0.5; cursor: not-allowed; }
412
426
  .status { min-height: 1.2em; margin-top: 0.5rem; font-size: 0.85rem; color: var(--muted); }
413
427
  .status.error { color: var(--bad); }
414
- main { padding: 1rem 1.5rem 2rem; max-width: 900px; margin: 0 auto; }
428
+ main { padding: 1rem 1.5rem max(2rem, env(safe-area-inset-bottom)); max-width: 900px; margin: 0 auto; }
415
429
  .add-boat-row { display: flex; gap: 0.5rem; margin-bottom: 1rem; flex-wrap: wrap; }
416
430
  .add-boat-row input[type='text'] { flex: 1; min-width: 12rem; padding: 0.45rem 0.6rem; background: var(--panel); color: var(--text); border: 1px solid var(--border); border-radius: 6px; font-size: 0.9rem; }
417
431
  .add-boat-row input[type='number'] { width: 6rem; padding: 0.45rem 0.6rem; background: var(--panel); color: var(--text); border: 1px solid var(--border); border-radius: 6px; font-size: 0.9rem; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "signalk-race-control",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
4
4
  "description": "SignalK plugin and webapp for tracking elapsed and handicap-corrected (Time-on-Time) race time, with a per-boat editable TCF and boat names pulled from AIS when available.",
5
5
  "main": "index.js",
6
6
  "keywords": [