@tomorrowos/sdk 0.6.2 → 0.6.4
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/dist/tomorrowos.d.ts
CHANGED
|
@@ -109,6 +109,10 @@ export declare class TomorrowOS extends EventEmitter {
|
|
|
109
109
|
};
|
|
110
110
|
/** List paired devices with live connection + timing fields for the CMS panel. */
|
|
111
111
|
listDevices(): Promise<DeviceListItem[]>;
|
|
112
|
+
setDeviceName(deviceId: string, deviceName: string): Promise<{
|
|
113
|
+
deviceId: string;
|
|
114
|
+
deviceName: string;
|
|
115
|
+
}>;
|
|
112
116
|
private pushDeviceLog;
|
|
113
117
|
private getDeviceLogs;
|
|
114
118
|
private isDeviceConnected;
|
package/dist/tomorrowos.d.ts.map
CHANGED
|
@@ -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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"}
|
package/dist/tomorrowos.js
CHANGED
|
@@ -352,6 +352,25 @@ export class TomorrowOS extends EventEmitter {
|
|
|
352
352
|
};
|
|
353
353
|
}));
|
|
354
354
|
}
|
|
355
|
+
async setDeviceName(deviceId, deviceName) {
|
|
356
|
+
const id = String(deviceId || "").trim();
|
|
357
|
+
if (!id) {
|
|
358
|
+
throw new Error("deviceId is required");
|
|
359
|
+
}
|
|
360
|
+
const existing = await this.store.getPairedDevice(id);
|
|
361
|
+
if (!existing) {
|
|
362
|
+
throw new Error("Device is not paired");
|
|
363
|
+
}
|
|
364
|
+
const normalized = String(deviceName || "").trim();
|
|
365
|
+
if (!normalized) {
|
|
366
|
+
throw new Error("deviceName is required");
|
|
367
|
+
}
|
|
368
|
+
await this.store.setPairedDevice(id, {
|
|
369
|
+
...existing,
|
|
370
|
+
deviceName: normalized
|
|
371
|
+
});
|
|
372
|
+
return { deviceId: id, deviceName: normalized };
|
|
373
|
+
}
|
|
355
374
|
pushDeviceLog(deviceId, entry) {
|
|
356
375
|
const key = String(deviceId || "").trim();
|
|
357
376
|
if (!key)
|
|
@@ -949,6 +968,20 @@ export class TomorrowOS extends EventEmitter {
|
|
|
949
968
|
sendJson(res, 200, { status: "success", devices });
|
|
950
969
|
return;
|
|
951
970
|
}
|
|
971
|
+
const deviceNamePatch = /^\/device\/([^/]+)\/name$/.exec(pathname);
|
|
972
|
+
if (req.method === "PATCH" && deviceNamePatch) {
|
|
973
|
+
const deviceId = decodeURIComponent(deviceNamePatch[1]);
|
|
974
|
+
const body = (await readJsonBody(req));
|
|
975
|
+
try {
|
|
976
|
+
const result = await this.setDeviceName(deviceId, typeof body.deviceName === "string" ? body.deviceName : "");
|
|
977
|
+
sendJson(res, 200, { status: "success", ...result });
|
|
978
|
+
}
|
|
979
|
+
catch (e) {
|
|
980
|
+
const msg = e instanceof Error ? e.message : "Rename failed";
|
|
981
|
+
sendJson(res, 400, { status: "failed", error: msg });
|
|
982
|
+
}
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
952
985
|
if (req.method === "GET" && pathname === "/playlists") {
|
|
953
986
|
const playlists = await this.playlists.listPlaylists();
|
|
954
987
|
sendJson(res, 200, { status: "success", playlists });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tomorrowos/sdk",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.4",
|
|
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.6.
|
|
3
|
+
"version": "0.6.4",
|
|
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",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"build-player": "tomorrowos build --platform tizen"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@tomorrowos/sdk": "^0.6.
|
|
13
|
+
"@tomorrowos/sdk": "^0.6.4",
|
|
14
14
|
"dotenv": "^17.2.3"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
@@ -17,6 +17,10 @@ let editorItems = [];
|
|
|
17
17
|
|
|
18
18
|
/** @type {string|null} */
|
|
19
19
|
let publishModalDeviceId = null;
|
|
20
|
+
/** @type {string|null} */
|
|
21
|
+
let editingDeviceNameId = null;
|
|
22
|
+
/** @type {string} */
|
|
23
|
+
let editingDeviceNameValue = "";
|
|
20
24
|
|
|
21
25
|
let devicePollTimer = null;
|
|
22
26
|
let uploadQueue = [];
|
|
@@ -660,13 +664,65 @@ function renderDeviceCards() {
|
|
|
660
664
|
|
|
661
665
|
const header = document.createElement("div");
|
|
662
666
|
header.className = "device-card-header";
|
|
667
|
+
const headerMain = document.createElement("div");
|
|
668
|
+
headerMain.className = "device-card-header-main";
|
|
663
669
|
const led = document.createElement("span");
|
|
664
670
|
led.className = `status-led ${device.connected ? "status-led--online" : "status-led--offline"}`;
|
|
665
671
|
const title = document.createElement("h3");
|
|
666
672
|
title.className = "device-card-title";
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
673
|
+
const isEditingName = editingDeviceNameId === device.deviceId;
|
|
674
|
+
if (isEditingName) {
|
|
675
|
+
const input = document.createElement("input");
|
|
676
|
+
input.type = "text";
|
|
677
|
+
input.className = "device-card-title-input";
|
|
678
|
+
input.value = editingDeviceNameValue || device.deviceName || "Screen";
|
|
679
|
+
input.placeholder = "Device name";
|
|
680
|
+
input.addEventListener("input", (ev) => {
|
|
681
|
+
editingDeviceNameValue = String(ev.target.value || "");
|
|
682
|
+
});
|
|
683
|
+
input.addEventListener("keydown", (ev) => {
|
|
684
|
+
if (ev.key === "Enter") {
|
|
685
|
+
ev.preventDefault();
|
|
686
|
+
void submitInlineDeviceRename(device.deviceId);
|
|
687
|
+
} else if (ev.key === "Escape") {
|
|
688
|
+
ev.preventDefault();
|
|
689
|
+
cancelInlineDeviceRename();
|
|
690
|
+
}
|
|
691
|
+
});
|
|
692
|
+
title.appendChild(input);
|
|
693
|
+
} else {
|
|
694
|
+
title.textContent = device.deviceName || "Screen";
|
|
695
|
+
}
|
|
696
|
+
headerMain.appendChild(led);
|
|
697
|
+
headerMain.appendChild(title);
|
|
698
|
+
|
|
699
|
+
const headerActions = document.createElement("div");
|
|
700
|
+
headerActions.className = "device-card-header-actions";
|
|
701
|
+
if (isEditingName) {
|
|
702
|
+
const saveBtn = document.createElement("button");
|
|
703
|
+
saveBtn.type = "button";
|
|
704
|
+
saveBtn.className = "primary";
|
|
705
|
+
saveBtn.textContent = "Save";
|
|
706
|
+
saveBtn.addEventListener("click", () =>
|
|
707
|
+
void submitInlineDeviceRename(device.deviceId)
|
|
708
|
+
);
|
|
709
|
+
const cancelBtn = document.createElement("button");
|
|
710
|
+
cancelBtn.type = "button";
|
|
711
|
+
cancelBtn.textContent = "Cancel";
|
|
712
|
+
cancelBtn.addEventListener("click", cancelInlineDeviceRename);
|
|
713
|
+
headerActions.appendChild(saveBtn);
|
|
714
|
+
headerActions.appendChild(cancelBtn);
|
|
715
|
+
} else {
|
|
716
|
+
const renameBtn = document.createElement("button");
|
|
717
|
+
renameBtn.type = "button";
|
|
718
|
+
renameBtn.textContent = "Rename";
|
|
719
|
+
renameBtn.addEventListener("click", () =>
|
|
720
|
+
startInlineDeviceRename(device.deviceId, device.deviceName)
|
|
721
|
+
);
|
|
722
|
+
headerActions.appendChild(renameBtn);
|
|
723
|
+
}
|
|
724
|
+
header.appendChild(headerMain);
|
|
725
|
+
header.appendChild(headerActions);
|
|
670
726
|
|
|
671
727
|
const published = document.createElement("ul");
|
|
672
728
|
published.className = "device-published-list";
|
|
@@ -1053,6 +1109,48 @@ async function unpairDevice(deviceId) {
|
|
|
1053
1109
|
if (res.ok) await fetchDevices();
|
|
1054
1110
|
}
|
|
1055
1111
|
|
|
1112
|
+
async function renameDevice(deviceId, currentName) {
|
|
1113
|
+
if (!deviceId) return false;
|
|
1114
|
+
const trimmed = String(currentName || "").trim();
|
|
1115
|
+
if (!trimmed) {
|
|
1116
|
+
alert("Device name cannot be empty.");
|
|
1117
|
+
return false;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
const res = await fetch(`/device/${encodeURIComponent(deviceId)}/name`, {
|
|
1121
|
+
method: "PATCH",
|
|
1122
|
+
headers: { "Content-Type": "application/json" },
|
|
1123
|
+
body: JSON.stringify({ deviceName: trimmed })
|
|
1124
|
+
});
|
|
1125
|
+
const data = await res.json();
|
|
1126
|
+
showResult({ deviceId, rename: data });
|
|
1127
|
+
if (!res.ok) {
|
|
1128
|
+
alert(data.error || "Rename failed");
|
|
1129
|
+
return false;
|
|
1130
|
+
}
|
|
1131
|
+
return true;
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
function startInlineDeviceRename(deviceId, currentName) {
|
|
1135
|
+
editingDeviceNameId = deviceId;
|
|
1136
|
+
editingDeviceNameValue = String(currentName || "").trim() || "Screen";
|
|
1137
|
+
renderDeviceCards();
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
function cancelInlineDeviceRename() {
|
|
1141
|
+
editingDeviceNameId = null;
|
|
1142
|
+
editingDeviceNameValue = "";
|
|
1143
|
+
renderDeviceCards();
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
async function submitInlineDeviceRename(deviceId) {
|
|
1147
|
+
const ok = await renameDevice(deviceId, editingDeviceNameValue);
|
|
1148
|
+
if (!ok) return;
|
|
1149
|
+
editingDeviceNameId = null;
|
|
1150
|
+
editingDeviceNameValue = "";
|
|
1151
|
+
await fetchDevices();
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1056
1154
|
async function deviceAction(deviceId, action) {
|
|
1057
1155
|
if (!deviceId) return;
|
|
1058
1156
|
if (action === "reboot" && !confirm("Reboot this device?")) return;
|
|
@@ -141,15 +141,45 @@ body {
|
|
|
141
141
|
.device-card-header {
|
|
142
142
|
display: flex;
|
|
143
143
|
align-items: center;
|
|
144
|
-
|
|
144
|
+
justify-content: space-between;
|
|
145
|
+
gap: 0.35rem;
|
|
145
146
|
margin-bottom: 0.65rem;
|
|
146
147
|
}
|
|
147
148
|
|
|
149
|
+
.device-card-header-main {
|
|
150
|
+
display: flex;
|
|
151
|
+
align-items: center;
|
|
152
|
+
gap: 0.5rem;
|
|
153
|
+
min-width: 0;
|
|
154
|
+
flex: 1;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.device-card-header-actions {
|
|
158
|
+
display: flex;
|
|
159
|
+
align-items: center;
|
|
160
|
+
gap: 0.35rem;
|
|
161
|
+
flex-shrink: 0;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.device-card-header-actions button {
|
|
165
|
+
font-size: 0.78rem;
|
|
166
|
+
padding: 0.35rem 0.6rem;
|
|
167
|
+
}
|
|
168
|
+
|
|
148
169
|
.device-card-title {
|
|
149
170
|
margin: 0;
|
|
150
171
|
font-size: 0.95rem;
|
|
151
172
|
font-weight: 600;
|
|
152
173
|
line-height: 1.2;
|
|
174
|
+
min-width: 0;
|
|
175
|
+
flex: 1;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
.device-card-title-input {
|
|
179
|
+
width: 100%;
|
|
180
|
+
min-width: 0;
|
|
181
|
+
font-size: 0.95rem;
|
|
182
|
+
font-weight: 600;
|
|
153
183
|
}
|
|
154
184
|
|
|
155
185
|
.status-led {
|