@tomorrowos/sdk 0.7.3 → 0.7.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tomorrowos/sdk",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.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.7.
|
|
3
|
+
"version": "0.7.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.7.
|
|
13
|
+
"@tomorrowos/sdk": "^0.7.4",
|
|
14
14
|
"dotenv": "^17.2.3"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
@@ -103,6 +103,7 @@
|
|
|
103
103
|
<h2>Assets</h2>
|
|
104
104
|
<button type="button" class="primary" id="addAssetBtn" title="Add image or video">+</button>
|
|
105
105
|
</div>
|
|
106
|
+
<p class="hint playlist-assets-hint">Drag ⋮⋮ to reorder assets. Save playlist to keep the new order.</p>
|
|
106
107
|
<input
|
|
107
108
|
type="file"
|
|
108
109
|
id="fileInput"
|
|
@@ -15,6 +15,9 @@ let playlistDraftActive = false;
|
|
|
15
15
|
/** @type {{ id: string, assetId?: string, url: string, name: string, type: string, durationMs: number }[]} */
|
|
16
16
|
let editorItems = [];
|
|
17
17
|
|
|
18
|
+
/** Item id currently being dragged in the asset list (reorder). */
|
|
19
|
+
let draggingEditorItemId = null;
|
|
20
|
+
|
|
18
21
|
/** @type {string|null} */
|
|
19
22
|
let publishModalDeviceId = null;
|
|
20
23
|
let publishInProgress = false;
|
|
@@ -670,9 +673,75 @@ function loadEditorFromSelection() {
|
|
|
670
673
|
updatePlaylistEditorVisibility();
|
|
671
674
|
}
|
|
672
675
|
|
|
676
|
+
function clearPlaylistItemDropTargets() {
|
|
677
|
+
document
|
|
678
|
+
.querySelectorAll(".playlist-item--drop-target, .playlist-item--dragging")
|
|
679
|
+
.forEach((el) => {
|
|
680
|
+
el.classList.remove("playlist-item--drop-target", "playlist-item--dragging");
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
function reorderEditorItems(fromId, toId) {
|
|
685
|
+
const fromIdx = editorItems.findIndex((x) => x.id === fromId);
|
|
686
|
+
const toIdx = editorItems.findIndex((x) => x.id === toId);
|
|
687
|
+
if (fromIdx < 0 || toIdx < 0 || fromIdx === toIdx) return;
|
|
688
|
+
const [moved] = editorItems.splice(fromIdx, 1);
|
|
689
|
+
editorItems.splice(toIdx, 0, moved);
|
|
690
|
+
renderEditorAssets();
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
function attachPlaylistItemDragDrop(li, item) {
|
|
694
|
+
li.dataset.itemId = item.id;
|
|
695
|
+
|
|
696
|
+
const handle = document.createElement("button");
|
|
697
|
+
handle.type = "button";
|
|
698
|
+
handle.className = "playlist-item-drag-handle";
|
|
699
|
+
handle.setAttribute("aria-label", "Drag to reorder");
|
|
700
|
+
handle.title = "Drag to reorder";
|
|
701
|
+
handle.textContent = "⋮⋮";
|
|
702
|
+
handle.draggable = true;
|
|
703
|
+
|
|
704
|
+
handle.addEventListener("dragstart", (e) => {
|
|
705
|
+
e.dataTransfer.setData("text/plain", item.id);
|
|
706
|
+
e.dataTransfer.effectAllowed = "move";
|
|
707
|
+
draggingEditorItemId = item.id;
|
|
708
|
+
li.classList.add("playlist-item--dragging");
|
|
709
|
+
});
|
|
710
|
+
|
|
711
|
+
handle.addEventListener("dragend", () => {
|
|
712
|
+
draggingEditorItemId = null;
|
|
713
|
+
clearPlaylistItemDropTargets();
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
li.addEventListener("dragover", (e) => {
|
|
717
|
+
e.preventDefault();
|
|
718
|
+
e.dataTransfer.dropEffect = "move";
|
|
719
|
+
if (draggingEditorItemId && draggingEditorItemId !== item.id) {
|
|
720
|
+
li.classList.add("playlist-item--drop-target");
|
|
721
|
+
}
|
|
722
|
+
});
|
|
723
|
+
|
|
724
|
+
li.addEventListener("dragleave", (e) => {
|
|
725
|
+
if (!li.contains(e.relatedTarget)) {
|
|
726
|
+
li.classList.remove("playlist-item--drop-target");
|
|
727
|
+
}
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
li.addEventListener("drop", (e) => {
|
|
731
|
+
e.preventDefault();
|
|
732
|
+
li.classList.remove("playlist-item--drop-target");
|
|
733
|
+
const fromId = e.dataTransfer.getData("text/plain") || draggingEditorItemId;
|
|
734
|
+
if (!fromId || fromId === item.id) return;
|
|
735
|
+
reorderEditorItems(fromId, item.id);
|
|
736
|
+
});
|
|
737
|
+
|
|
738
|
+
li.insertBefore(handle, li.firstChild);
|
|
739
|
+
}
|
|
740
|
+
|
|
673
741
|
function renderEditorAssets() {
|
|
674
742
|
const list = document.getElementById("playlistList");
|
|
675
743
|
const empty = document.getElementById("playlistEmpty");
|
|
744
|
+
draggingEditorItemId = null;
|
|
676
745
|
list.querySelectorAll(".playlist-item").forEach((el) => el.remove());
|
|
677
746
|
|
|
678
747
|
if (!isPlaylistEditorOpen()) {
|
|
@@ -696,6 +765,7 @@ function renderEditorAssets() {
|
|
|
696
765
|
if (item.type === "image" || item.type === "video") {
|
|
697
766
|
const thumb = document.createElement(item.type === "video" ? "video" : "img");
|
|
698
767
|
thumb.className = "playlist-item-thumb";
|
|
768
|
+
thumb.draggable = false;
|
|
699
769
|
try {
|
|
700
770
|
thumb.src = absoluteMediaUrl(item.url);
|
|
701
771
|
} catch {
|
|
@@ -752,6 +822,7 @@ function renderEditorAssets() {
|
|
|
752
822
|
li.appendChild(name);
|
|
753
823
|
li.appendChild(meta);
|
|
754
824
|
li.appendChild(actions);
|
|
825
|
+
attachPlaylistItemDragDrop(li, item);
|
|
755
826
|
list.appendChild(li);
|
|
756
827
|
}
|
|
757
828
|
}
|
|
@@ -429,12 +429,52 @@ button.danger {
|
|
|
429
429
|
font-size: 0.875rem;
|
|
430
430
|
}
|
|
431
431
|
|
|
432
|
+
.playlist-assets-hint {
|
|
433
|
+
margin: 0 0 0.75rem;
|
|
434
|
+
font-size: 0.78rem;
|
|
435
|
+
}
|
|
436
|
+
|
|
432
437
|
.playlist-item {
|
|
433
438
|
border: 1px solid #e4e1dc;
|
|
434
439
|
border-radius: 8px;
|
|
435
440
|
padding: 0.65rem;
|
|
436
441
|
margin-bottom: 0.5rem;
|
|
437
442
|
background: #fafaf9;
|
|
443
|
+
position: relative;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
.playlist-item--dragging {
|
|
447
|
+
opacity: 0.55;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
.playlist-item--drop-target {
|
|
451
|
+
border-color: #ff8a3d;
|
|
452
|
+
box-shadow: 0 0 0 2px rgba(255, 138, 61, 0.25);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
.playlist-item-drag-handle {
|
|
456
|
+
display: block;
|
|
457
|
+
width: 100%;
|
|
458
|
+
margin: 0 0 0.45rem;
|
|
459
|
+
padding: 0.2rem 0;
|
|
460
|
+
border: 0;
|
|
461
|
+
border-radius: 4px;
|
|
462
|
+
background: transparent;
|
|
463
|
+
color: #888;
|
|
464
|
+
font-size: 0.95rem;
|
|
465
|
+
line-height: 1;
|
|
466
|
+
letter-spacing: 0.08em;
|
|
467
|
+
cursor: grab;
|
|
468
|
+
touch-action: none;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
.playlist-item-drag-handle:active {
|
|
472
|
+
cursor: grabbing;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
.playlist-item-drag-handle:hover {
|
|
476
|
+
color: #444;
|
|
477
|
+
background: #f0eeea;
|
|
438
478
|
}
|
|
439
479
|
|
|
440
480
|
.playlist-item-thumb {
|