@tomorrowos/sdk 0.6.1 → 0.6.3
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)
|
|
@@ -889,7 +908,7 @@ export class TomorrowOS extends EventEmitter {
|
|
|
889
908
|
}
|
|
890
909
|
}
|
|
891
910
|
async captureDeviceScreenshot(deviceId) {
|
|
892
|
-
const result = await this.sendDeviceCommand(deviceId, "device.
|
|
911
|
+
const result = await this.sendDeviceCommand(deviceId, "device.captureScreen", {});
|
|
893
912
|
if (result.status === "failed") {
|
|
894
913
|
throw new Error(String(result.error ?? "Screenshot failed"));
|
|
895
914
|
}
|
|
@@ -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.3",
|
|
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.3",
|
|
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.3",
|
|
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 = [];
|
|
@@ -664,7 +668,29 @@ function renderDeviceCards() {
|
|
|
664
668
|
led.className = `status-led ${device.connected ? "status-led--online" : "status-led--offline"}`;
|
|
665
669
|
const title = document.createElement("h3");
|
|
666
670
|
title.className = "device-card-title";
|
|
667
|
-
|
|
671
|
+
const isEditingName = editingDeviceNameId === device.deviceId;
|
|
672
|
+
if (isEditingName) {
|
|
673
|
+
const input = document.createElement("input");
|
|
674
|
+
input.type = "text";
|
|
675
|
+
input.value = editingDeviceNameValue || device.deviceName || "Screen";
|
|
676
|
+
input.placeholder = "Device name";
|
|
677
|
+
input.style.minWidth = "12rem";
|
|
678
|
+
input.addEventListener("input", (ev) => {
|
|
679
|
+
editingDeviceNameValue = String(ev.target.value || "");
|
|
680
|
+
});
|
|
681
|
+
input.addEventListener("keydown", (ev) => {
|
|
682
|
+
if (ev.key === "Enter") {
|
|
683
|
+
ev.preventDefault();
|
|
684
|
+
void submitInlineDeviceRename(device.deviceId);
|
|
685
|
+
} else if (ev.key === "Escape") {
|
|
686
|
+
ev.preventDefault();
|
|
687
|
+
cancelInlineDeviceRename();
|
|
688
|
+
}
|
|
689
|
+
});
|
|
690
|
+
title.appendChild(input);
|
|
691
|
+
} else {
|
|
692
|
+
title.textContent = device.deviceName || "Screen";
|
|
693
|
+
}
|
|
668
694
|
header.appendChild(led);
|
|
669
695
|
header.appendChild(title);
|
|
670
696
|
|
|
@@ -760,6 +786,26 @@ function renderDeviceCards() {
|
|
|
760
786
|
latestScreenshotBtn.textContent = "Last screen";
|
|
761
787
|
latestScreenshotBtn.addEventListener("click", () => viewLatestScreenshot(device.deviceId));
|
|
762
788
|
|
|
789
|
+
const renameBtn = document.createElement("button");
|
|
790
|
+
renameBtn.type = "button";
|
|
791
|
+
if (isEditingName) {
|
|
792
|
+
renameBtn.className = "primary";
|
|
793
|
+
renameBtn.textContent = "Save";
|
|
794
|
+
renameBtn.addEventListener("click", () =>
|
|
795
|
+
void submitInlineDeviceRename(device.deviceId)
|
|
796
|
+
);
|
|
797
|
+
} else {
|
|
798
|
+
renameBtn.textContent = "Rename";
|
|
799
|
+
renameBtn.addEventListener("click", () =>
|
|
800
|
+
startInlineDeviceRename(device.deviceId, device.deviceName)
|
|
801
|
+
);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
const cancelRenameBtn = document.createElement("button");
|
|
805
|
+
cancelRenameBtn.type = "button";
|
|
806
|
+
cancelRenameBtn.textContent = "Cancel";
|
|
807
|
+
cancelRenameBtn.addEventListener("click", cancelInlineDeviceRename);
|
|
808
|
+
|
|
763
809
|
const unpairBtn = document.createElement("button");
|
|
764
810
|
unpairBtn.type = "button";
|
|
765
811
|
unpairBtn.className = "danger";
|
|
@@ -774,6 +820,8 @@ function renderDeviceCards() {
|
|
|
774
820
|
actions.appendChild(logsBtn);
|
|
775
821
|
actions.appendChild(screenshotBtn);
|
|
776
822
|
actions.appendChild(latestScreenshotBtn);
|
|
823
|
+
actions.appendChild(renameBtn);
|
|
824
|
+
if (isEditingName) actions.appendChild(cancelRenameBtn);
|
|
777
825
|
actions.appendChild(unpairBtn);
|
|
778
826
|
|
|
779
827
|
card.appendChild(header);
|
|
@@ -1053,6 +1101,48 @@ async function unpairDevice(deviceId) {
|
|
|
1053
1101
|
if (res.ok) await fetchDevices();
|
|
1054
1102
|
}
|
|
1055
1103
|
|
|
1104
|
+
async function renameDevice(deviceId, currentName) {
|
|
1105
|
+
if (!deviceId) return false;
|
|
1106
|
+
const trimmed = String(currentName || "").trim();
|
|
1107
|
+
if (!trimmed) {
|
|
1108
|
+
alert("Device name cannot be empty.");
|
|
1109
|
+
return false;
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
const res = await fetch(`/device/${encodeURIComponent(deviceId)}/name`, {
|
|
1113
|
+
method: "PATCH",
|
|
1114
|
+
headers: { "Content-Type": "application/json" },
|
|
1115
|
+
body: JSON.stringify({ deviceName: trimmed })
|
|
1116
|
+
});
|
|
1117
|
+
const data = await res.json();
|
|
1118
|
+
showResult({ deviceId, rename: data });
|
|
1119
|
+
if (!res.ok) {
|
|
1120
|
+
alert(data.error || "Rename failed");
|
|
1121
|
+
return false;
|
|
1122
|
+
}
|
|
1123
|
+
return true;
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
function startInlineDeviceRename(deviceId, currentName) {
|
|
1127
|
+
editingDeviceNameId = deviceId;
|
|
1128
|
+
editingDeviceNameValue = String(currentName || "").trim() || "Screen";
|
|
1129
|
+
renderDeviceCards();
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
function cancelInlineDeviceRename() {
|
|
1133
|
+
editingDeviceNameId = null;
|
|
1134
|
+
editingDeviceNameValue = "";
|
|
1135
|
+
renderDeviceCards();
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
async function submitInlineDeviceRename(deviceId) {
|
|
1139
|
+
const ok = await renameDevice(deviceId, editingDeviceNameValue);
|
|
1140
|
+
if (!ok) return;
|
|
1141
|
+
editingDeviceNameId = null;
|
|
1142
|
+
editingDeviceNameValue = "";
|
|
1143
|
+
await fetchDevices();
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1056
1146
|
async function deviceAction(deviceId, action) {
|
|
1057
1147
|
if (!deviceId) return;
|
|
1058
1148
|
if (action === "reboot" && !confirm("Reboot this device?")) return;
|
|
@@ -1099,7 +1189,8 @@ async function captureDeviceScreenshot(deviceId) {
|
|
|
1099
1189
|
alert(data.error || "Screenshot failed");
|
|
1100
1190
|
return;
|
|
1101
1191
|
}
|
|
1102
|
-
|
|
1192
|
+
const capturedAt = formatDateTimeSeconds(data.screenshot?.capturedAt);
|
|
1193
|
+
alert(`Screenshot captured successfully${capturedAt ? ` at ${capturedAt}` : ""}.`);
|
|
1103
1194
|
}
|
|
1104
1195
|
|
|
1105
1196
|
async function viewLatestScreenshot(deviceId) {
|