@tomorrowos/sdk 0.8.9 → 0.9.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.
package/REPLIT_SETUP.md CHANGED
@@ -232,7 +232,7 @@ Allowed extras (optional): `"build-player": "tomorrowos build --platform tizen"`
232
232
  "node": ">=20"
233
233
  },
234
234
  "dependencies": {
235
- "@tomorrowos/sdk": "^0.8.8",
235
+ "@tomorrowos/sdk": "^0.9.1",
236
236
  "dotenv": "^17.2.3",
237
237
  "tsx": "^4.19.0"
238
238
  },
@@ -129,6 +129,8 @@ export declare class TomorrowOS extends EventEmitter {
129
129
  /** Prefer CMS-saved display name; fall back to handshake hardware model on first pair. */
130
130
  private resolveDeviceNameForPairing;
131
131
  private persistRegistryDisplayName;
132
+ /** First pair only — seed registry display name from device handshake when unset. */
133
+ private seedRegistryDisplayNameIfEmpty;
132
134
  private pushDeviceLog;
133
135
  private getDeviceLogs;
134
136
  private isDeviceConnected;
@@ -1 +1 @@
1
- {"version":3,"file":"tomorrowos.d.ts","sourceRoot":"","sources":["../src/tomorrowos.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tomorrowos.d.ts","sourceRoot":"","sources":["../src/tomorrowos.ts"],"names":[],"mappings":"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"}
@@ -267,6 +267,9 @@ export class TomorrowOS extends EventEmitter {
267
267
  lastOnlineAt: this.isDeviceConnected(deviceId) ? now : undefined,
268
268
  lastOfflineAt: this.isDeviceConnected(deviceId) ? undefined : now
269
269
  });
270
+ if (deviceName) {
271
+ await this.seedRegistryDisplayNameIfEmpty(deviceId, deviceName);
272
+ }
270
273
  await this.store.deletePendingCode(normalized);
271
274
  const ws = this.devices.get(deviceId);
272
275
  if (ws && ws.readyState === WebSocket.OPEN) {
@@ -422,6 +425,16 @@ export class TomorrowOS extends EventEmitter {
422
425
  displayName: displayName.trim()
423
426
  });
424
427
  }
428
+ /** First pair only — seed registry display name from device handshake when unset. */
429
+ async seedRegistryDisplayNameIfEmpty(deviceId, displayName) {
430
+ const reg = await this.store.getDeviceRegistry(deviceId);
431
+ if (!reg || reg.displayName?.trim())
432
+ return;
433
+ await this.store.setDeviceRegistry(deviceId, {
434
+ ...reg,
435
+ displayName: displayName.trim()
436
+ });
437
+ }
425
438
  pushDeviceLog(deviceId, entry) {
426
439
  const key = String(deviceId || "").trim();
427
440
  if (!key)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tomorrowos/sdk",
3
- "version": "0.8.9",
3
+ "version": "0.9.1",
4
4
  "description": "TomorrowOS CMS server SDK - WebSocket transport, pairing, device commands, optional static CMS UI. Includes CLI (tomorrowos init / build) and starter templates.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "my-cms",
3
- "version": "0.8.9",
3
+ "version": "0.9.1",
4
4
  "description": "CMS server on @tomorrowos/sdk. Add your UI (React, static files, etc.) alongside this server.",
5
5
  "private": true,
6
6
  "type": "module",
@@ -13,7 +13,7 @@
13
13
  "build-player": "tomorrowos build --platform tizen"
14
14
  },
15
15
  "dependencies": {
16
- "@tomorrowos/sdk": "^0.8.9",
16
+ "@tomorrowos/sdk": "^0.9.1",
17
17
  "dotenv": "^17.2.3",
18
18
  "tsx": "^4.19.0"
19
19
  },
@@ -0,0 +1,7 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" role="img" aria-label="Android">
2
+ <path fill="#3DDC84" d="M12 20c-2.2 0-4 1.8-4 4v8c0 2.2 1.8 4 4 4h24c2.2 0 4-1.8 4-4v-8c0-2.2-1.8-4-4-4H12z"/>
3
+ <path fill="#3DDC84" d="M16 14l-3-5M32 14l3-5M18 10h12"/>
4
+ <circle cx="18" cy="24" r="2" fill="#fff"/>
5
+ <circle cx="30" cy="24" r="2" fill="#fff"/>
6
+ <path fill="#3DDC84" d="M8 22H6v6h2v-6zm34 0h-2v6h2v-6z"/>
7
+ </svg>
@@ -0,0 +1,5 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 40" role="img" aria-label="BrightSign">
2
+ <rect x="0" y="8" width="24" height="24" rx="4" fill="#E85D04"/>
3
+ <path d="M10 16 L18 20 L10 24 Z" fill="#fff"/>
4
+ <text x="32" y="27" font-family="Segoe UI, Arial, sans-serif" font-size="22" font-weight="700" fill="#1a1a1a">BrightSign</text>
5
+ </svg>
@@ -0,0 +1,5 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 48" role="img" aria-label="LG webOS">
2
+ <circle cx="24" cy="24" r="20" fill="#A50034"/>
3
+ <text x="24" y="30" text-anchor="middle" font-family="Segoe UI, Arial, sans-serif" font-size="18" font-weight="700" fill="#fff">LG</text>
4
+ <text x="56" y="32" font-family="Segoe UI, Arial, sans-serif" font-size="24" font-weight="600" fill="#555">webOS</text>
5
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 40" role="img" aria-label="Samsung">
2
+ <text x="0" y="30" font-family="Segoe UI, Arial, sans-serif" font-size="26" font-weight="700" letter-spacing="0.12em" fill="#1428A0">SAMSUNG</text>
3
+ </svg>
@@ -0,0 +1,12 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 96" role="img" aria-hidden="true">
2
+ <rect x="8" y="36" width="104" height="48" rx="6" fill="#f4f3f0" stroke="#8a8782" stroke-width="2"/>
3
+ <rect x="8" y="28" width="104" height="12" rx="4" fill="#e4e1dc" stroke="#8a8782" stroke-width="2"/>
4
+ <rect x="48" y="18" width="24" height="14" rx="3" fill="none" stroke="#8a8782" stroke-width="2"/>
5
+ <rect x="20" y="52" width="18" height="14" rx="2" fill="#fff" stroke="#c9c5bf" stroke-width="1.5"/>
6
+ <rect x="51" y="52" width="18" height="14" rx="2" fill="#fff" stroke="#c9c5bf" stroke-width="1.5"/>
7
+ <rect x="82" y="52" width="18" height="14" rx="2" fill="#fff" stroke="#c9c5bf" stroke-width="1.5"/>
8
+ <path d="M62 8 L78 28 L46 28 Z" fill="#ff8a3d" stroke="#e67320" stroke-width="1.5" stroke-linejoin="round"/>
9
+ <rect x="58" y="28" width="8" height="18" fill="#6e6b67"/>
10
+ <path d="M88 12 L96 20 L92 24 L84 16 Z" fill="#6e6b67"/>
11
+ <rect x="84" y="20" width="14" height="4" rx="1" transform="rotate(-45 91 22)" fill="#8a8782"/>
12
+ </svg>
@@ -172,6 +172,58 @@
172
172
  </div>
173
173
  </div>
174
174
 
175
+ <button type="button" id="downloadPlayersBtn" class="download-players-trigger">
176
+ Download Players
177
+ </button>
178
+
179
+ <div id="downloadPlayersModal" class="modal hidden" role="dialog" aria-modal="true" aria-labelledby="downloadPlayersModalTitle">
180
+ <div class="modal-backdrop" data-close-download-players-modal="1"></div>
181
+ <div class="modal-card download-players-modal-card">
182
+ <h2 id="downloadPlayersModalTitle" class="visually-hidden">Download Players</h2>
183
+ <div class="player-platform-grid">
184
+ <div class="player-platform-cell">
185
+ <a
186
+ href="#download-brightsign"
187
+ class="player-platform-link"
188
+ data-player-download="brightsign"
189
+ target="_blank"
190
+ rel="noopener noreferrer"
191
+ >
192
+ <img src="./assets/player-download/brightsign.svg" alt="BrightSign" class="player-platform-logo player-platform-logo--wide" />
193
+ </a>
194
+ <p class="player-platform-caption">Supported Series 5 / 6</p>
195
+ </div>
196
+ <div class="player-platform-cell player-platform-cell--align-end">
197
+ <a
198
+ href="#download-samsung"
199
+ class="player-platform-link"
200
+ data-player-download="samsung"
201
+ target="_blank"
202
+ rel="noopener noreferrer"
203
+ >
204
+ <img src="./assets/player-download/samsung.svg" alt="Samsung" class="player-platform-logo player-platform-logo--wide" />
205
+ </a>
206
+ <p class="player-platform-caption">Supported Tizen 6.5+</p>
207
+ </div>
208
+ <div class="player-platform-cell">
209
+ <img src="./assets/player-download/android.svg" alt="Android" class="player-platform-logo player-platform-logo--icon" />
210
+ <p class="player-platform-caption player-platform-caption--muted">Launching Q4 2026</p>
211
+ </div>
212
+ <div class="player-platform-cell player-platform-cell--align-end">
213
+ <img src="./assets/player-download/lg-webos.svg" alt="LG webOS" class="player-platform-logo player-platform-logo--wide" />
214
+ <p class="player-platform-caption player-platform-caption--muted">Launching Q4 2026</p>
215
+ </div>
216
+ </div>
217
+ <div class="player-platform-diy">
218
+ <img src="./assets/player-download/toolbox.svg" alt="" class="player-platform-toolbox" />
219
+ <p class="player-platform-caption">Build your own player support</p>
220
+ </div>
221
+ <div class="modal-actions download-players-modal-actions">
222
+ <button type="button" data-close-download-players-modal="1">Close</button>
223
+ </div>
224
+ </div>
225
+ </div>
226
+
175
227
  <script src="./methods.js" defer></script>
176
228
  </body>
177
229
  </html>
@@ -1767,6 +1767,20 @@ function closeDownloadFailedModal() {
1767
1767
  document.getElementById("downloadFailedModal")?.classList.add("hidden");
1768
1768
  }
1769
1769
 
1770
+ function openDownloadPlayersModal() {
1771
+ document.getElementById("downloadPlayersModal")?.classList.remove("hidden");
1772
+ }
1773
+
1774
+ function closeDownloadPlayersModal() {
1775
+ document.getElementById("downloadPlayersModal")?.classList.add("hidden");
1776
+ }
1777
+
1778
+ function handlePlayerDownloadLinkClick(ev) {
1779
+ ev.preventDefault();
1780
+ const platform = ev.currentTarget?.dataset?.playerDownload || "unknown";
1781
+ console.info(`[CMS] Player download link placeholder (${platform}) — URL not configured yet.`);
1782
+ }
1783
+
1770
1784
  function sanitizeDownloadFilename(name) {
1771
1785
  const base = String(name || "asset").trim() || "asset";
1772
1786
  return base.replace(/[<>:"/\\|?*\x00-\x1f]/g, "_");
@@ -1850,6 +1864,14 @@ document.addEventListener("DOMContentLoaded", () => {
1850
1864
  el.addEventListener("click", closeDownloadFailedModal);
1851
1865
  });
1852
1866
 
1867
+ document.getElementById("downloadPlayersBtn")?.addEventListener("click", openDownloadPlayersModal);
1868
+ document.querySelectorAll("[data-close-download-players-modal]").forEach((el) => {
1869
+ el.addEventListener("click", closeDownloadPlayersModal);
1870
+ });
1871
+ document.querySelectorAll("[data-player-download]").forEach((el) => {
1872
+ el.addEventListener("click", handlePlayerDownloadLinkClick);
1873
+ });
1874
+
1853
1875
  document.getElementById("addAssetBtn")?.addEventListener("click", () => {
1854
1876
  if (uploadInProgress) return;
1855
1877
  if (!isPlaylistEditorOpen()) {
@@ -716,3 +716,127 @@ button.danger {
716
716
  gap: 0.5rem;
717
717
  margin-top: 1rem;
718
718
  }
719
+
720
+ .visually-hidden {
721
+ position: absolute;
722
+ width: 1px;
723
+ height: 1px;
724
+ padding: 0;
725
+ margin: -1px;
726
+ overflow: hidden;
727
+ clip: rect(0, 0, 0, 0);
728
+ white-space: nowrap;
729
+ border: 0;
730
+ }
731
+
732
+ .download-players-trigger {
733
+ position: fixed;
734
+ left: 1rem;
735
+ bottom: 1rem;
736
+ z-index: 900;
737
+ font: inherit;
738
+ font-size: 0.85rem;
739
+ font-weight: 600;
740
+ padding: 0.55rem 0.95rem;
741
+ border-radius: 8px;
742
+ border: 1px solid #d6d2cb;
743
+ background: #fff;
744
+ color: #0a0908;
745
+ cursor: pointer;
746
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
747
+ }
748
+
749
+ .download-players-trigger:hover {
750
+ background: #f5f3ef;
751
+ }
752
+
753
+ .download-players-modal-card {
754
+ width: min(92vw, 560px);
755
+ padding: 1.5rem 1.75rem 1.25rem;
756
+ }
757
+
758
+ .player-platform-grid {
759
+ display: grid;
760
+ grid-template-columns: 1fr 1fr;
761
+ gap: 1.75rem 2rem;
762
+ align-items: start;
763
+ }
764
+
765
+ .player-platform-cell {
766
+ display: flex;
767
+ flex-direction: column;
768
+ gap: 0.45rem;
769
+ min-height: 5.5rem;
770
+ }
771
+
772
+ .player-platform-cell--align-end {
773
+ align-items: flex-end;
774
+ text-align: right;
775
+ }
776
+
777
+ .player-platform-link {
778
+ display: inline-flex;
779
+ align-items: center;
780
+ text-decoration: none;
781
+ border-radius: 6px;
782
+ transition: opacity 120ms ease, transform 120ms ease;
783
+ }
784
+
785
+ .player-platform-link:hover {
786
+ opacity: 0.82;
787
+ transform: translateY(-1px);
788
+ }
789
+
790
+ .player-platform-link:focus-visible {
791
+ outline: 2px solid #ff8a3d;
792
+ outline-offset: 3px;
793
+ }
794
+
795
+ .player-platform-logo {
796
+ display: block;
797
+ object-fit: contain;
798
+ }
799
+
800
+ .player-platform-logo--wide {
801
+ height: 2.25rem;
802
+ width: auto;
803
+ max-width: 100%;
804
+ }
805
+
806
+ .player-platform-logo--icon {
807
+ height: 2.75rem;
808
+ width: 2.75rem;
809
+ }
810
+
811
+ .player-platform-caption {
812
+ margin: 0;
813
+ font-size: 0.78rem;
814
+ line-height: 1.35;
815
+ color: #444;
816
+ }
817
+
818
+ .player-platform-caption--muted {
819
+ color: #888;
820
+ }
821
+
822
+ .player-platform-diy {
823
+ margin-top: 1.35rem;
824
+ padding-top: 1.35rem;
825
+ border-top: 1px solid #e4e1dc;
826
+ display: flex;
827
+ flex-direction: column;
828
+ align-items: center;
829
+ gap: 0.55rem;
830
+ text-align: center;
831
+ }
832
+
833
+ .player-platform-toolbox {
834
+ width: 5.5rem;
835
+ height: auto;
836
+ display: block;
837
+ }
838
+
839
+ .download-players-modal-actions {
840
+ justify-content: center;
841
+ margin-top: 1.15rem;
842
+ }