@switchbot/homebridge-switchbot 5.1.0-beta.2 → 5.1.0-beta.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/.github/scripts/normalize-changelog-header.cjs +86 -0
- package/.github/scripts/npm-version-script-esm-auto.js +201 -0
- package/.github/scripts/resolve-version-bump-esm.js +118 -0
- package/.github/workflows/release.yml +4 -4
- package/CHANGELOG.md +18 -0
- package/dist/homebridge-ui/public/css/styles.css +1 -1
- package/dist/homebridge-ui/public/index.html +1 -5
- package/dist/homebridge-ui/public/js/api.d.ts +1 -0
- package/dist/homebridge-ui/public/js/api.d.ts.map +1 -1
- package/dist/homebridge-ui/public/js/api.js +14 -1
- package/dist/homebridge-ui/public/js/api.js.map +1 -1
- package/dist/homebridge-ui/public/js/api.ts +16 -1
- package/dist/homebridge-ui/public/js/app.js +54 -71
- package/dist/homebridge-ui/public/js/app.js.map +2 -2
- package/dist/homebridge-ui/public/js/discovery.d.ts.map +1 -1
- package/dist/homebridge-ui/public/js/discovery.js +0 -36
- package/dist/homebridge-ui/public/js/discovery.js.map +1 -1
- package/dist/homebridge-ui/public/js/discovery.ts +0 -37
- package/dist/homebridge-ui/public/js/render.d.ts.map +1 -1
- package/dist/homebridge-ui/public/js/render.js +38 -31
- package/dist/homebridge-ui/public/js/render.js.map +1 -1
- package/dist/homebridge-ui/public/js/render.ts +39 -34
- package/dist/homebridge-ui/public/js/toast.d.ts.map +1 -1
- package/dist/homebridge-ui/public/js/toast.js +2 -3
- package/dist/homebridge-ui/public/js/toast.js.map +1 -1
- package/dist/homebridge-ui/public/js/toast.ts +2 -3
- package/docs/variables/default.html +1 -1
- package/package.json +1 -1
- package/src/homebridge-ui/public/css/styles.css +1 -1
- package/src/homebridge-ui/public/index.html +0 -4
- package/src/homebridge-ui/public/js/api.ts +16 -1
- package/src/homebridge-ui/public/js/discovery.ts +0 -37
- package/src/homebridge-ui/public/js/render.ts +39 -34
- package/src/homebridge-ui/public/js/toast.ts +2 -3
|
@@ -299,10 +299,9 @@ function showToast(method, message, title = "SwitchBot") {
|
|
|
299
299
|
try {
|
|
300
300
|
const hb = typeof window !== "undefined" ? window.homebridge : void 0;
|
|
301
301
|
const toast = hb && typeof hb.toast === "object" ? hb.toast : void 0;
|
|
302
|
-
|
|
303
|
-
if (fn) {
|
|
302
|
+
if (toast && typeof toast[method] === "function") {
|
|
304
303
|
try {
|
|
305
|
-
|
|
304
|
+
toast[method](message, title);
|
|
306
305
|
return;
|
|
307
306
|
} catch (err) {
|
|
308
307
|
uiLog.warn(`Toast ${method} threw:`, err);
|
|
@@ -346,6 +345,7 @@ __export(api_exports, {
|
|
|
346
345
|
fetchBluetoothStatus: () => fetchBluetoothStatus,
|
|
347
346
|
fetchCredentialStatus: () => fetchCredentialStatus,
|
|
348
347
|
fetchDevices: () => fetchDevices,
|
|
348
|
+
normalizeBulkAddDevicesResponse: () => normalizeBulkAddDevicesResponse,
|
|
349
349
|
saveCredentials: () => saveCredentials,
|
|
350
350
|
syncParentPluginConfigFromDisk: () => syncParentPluginConfigFromDisk,
|
|
351
351
|
testDeviceConnection: () => testDeviceConnection,
|
|
@@ -563,7 +563,20 @@ async function addDevicesInBulk(devices) {
|
|
|
563
563
|
if (!resp || resp.success === false) {
|
|
564
564
|
throw new Error(resp?.data?.message || "Bulk add failed");
|
|
565
565
|
}
|
|
566
|
-
return resp
|
|
566
|
+
return normalizeBulkAddDevicesResponse(resp);
|
|
567
|
+
}
|
|
568
|
+
function normalizeBulkAddDevicesResponse(resp) {
|
|
569
|
+
const payload = resp?.data && typeof resp.data === "object" ? resp.data : resp;
|
|
570
|
+
const addedCount = Number(payload?.addedCount ?? payload?.added ?? 0);
|
|
571
|
+
const skippedCount = Number(payload?.skippedCount ?? payload?.skipped ?? 0);
|
|
572
|
+
const updatedCount = Number(payload?.updatedCount ?? payload?.updated ?? 0);
|
|
573
|
+
return {
|
|
574
|
+
...payload,
|
|
575
|
+
success: resp?.success ?? true,
|
|
576
|
+
addedCount,
|
|
577
|
+
skippedCount,
|
|
578
|
+
updatedCount
|
|
579
|
+
};
|
|
567
580
|
}
|
|
568
581
|
async function updateDevice(deviceId, configDeviceName, configDeviceType, options) {
|
|
569
582
|
if (typeof homebridge.getPluginConfig !== "function" || typeof homebridge.updatePluginConfig !== "function") {
|
|
@@ -999,7 +1012,6 @@ function setDiscoveryGroupExpanded(groupKey, expanded) {
|
|
|
999
1012
|
}
|
|
1000
1013
|
async function discoverDevices2() {
|
|
1001
1014
|
const btn = document.getElementById("discoverBtn");
|
|
1002
|
-
const cancelBtn = document.getElementById("cancelDiscoverBtn");
|
|
1003
1015
|
const status = document.getElementById("discoverStatus");
|
|
1004
1016
|
const phaseProgress = document.getElementById("discoverPhaseProgress");
|
|
1005
1017
|
const phaseFill = document.getElementById("discoverPhaseFill");
|
|
@@ -1027,7 +1039,6 @@ async function discoverDevices2() {
|
|
|
1027
1039
|
const startedAt = Date.now();
|
|
1028
1040
|
let phaseStartedAt = startedAt;
|
|
1029
1041
|
let phase = "Preparing discovery...";
|
|
1030
|
-
let cancelled = false;
|
|
1031
1042
|
const setPhase = (nextPhase) => {
|
|
1032
1043
|
phase = nextPhase;
|
|
1033
1044
|
phaseStartedAt = Date.now();
|
|
@@ -1464,31 +1475,8 @@ async function discoverDevices2() {
|
|
|
1464
1475
|
devicesFoundDisplay.style.display = "none";
|
|
1465
1476
|
devicesFoundDisplay.classList.remove("discovery-scanning-pulse");
|
|
1466
1477
|
}
|
|
1467
|
-
if (cancelBtn) {
|
|
1468
|
-
cancelBtn.style.display = "inline-block";
|
|
1469
|
-
cancelBtn.disabled = false;
|
|
1470
|
-
cancelBtn.onclick = () => {
|
|
1471
|
-
cancelled = true;
|
|
1472
|
-
const totalSeconds = Math.max(0, Math.floor((Date.now() - startedAt) / 1e3));
|
|
1473
|
-
status.textContent = `Discovery cancelled (${totalSeconds}s total)`;
|
|
1474
|
-
if (phaseProgress) {
|
|
1475
|
-
phaseProgress.style.display = "none";
|
|
1476
|
-
}
|
|
1477
|
-
if (devicesFoundDisplay) {
|
|
1478
|
-
devicesFoundDisplay.style.display = "none";
|
|
1479
|
-
devicesFoundDisplay.classList.remove("discovery-scanning-pulse");
|
|
1480
|
-
}
|
|
1481
|
-
cancelBtn.style.display = "none";
|
|
1482
|
-
btn.disabled = false;
|
|
1483
|
-
btn.textContent = "\u{1F50D} Discover Devices";
|
|
1484
|
-
hideBusyUi();
|
|
1485
|
-
};
|
|
1486
|
-
}
|
|
1487
1478
|
if (bleSettings.bleEnabled) {
|
|
1488
1479
|
const bleDevicesRaw = await discoverDevices("ble", bleSettings);
|
|
1489
|
-
if (cancelled) {
|
|
1490
|
-
return;
|
|
1491
|
-
}
|
|
1492
1480
|
discoveredDevices = dedupeById(bleDevicesRaw);
|
|
1493
1481
|
uiLog.info("BLE discover response:", bleDevicesRaw);
|
|
1494
1482
|
if (devicesFoundDisplay && bleDevicesRaw.length > 0) {
|
|
@@ -1509,9 +1497,6 @@ async function discoverDevices2() {
|
|
|
1509
1497
|
renderProgress();
|
|
1510
1498
|
try {
|
|
1511
1499
|
const openApiDevicesRaw = await discoverDevices("openapi");
|
|
1512
|
-
if (cancelled) {
|
|
1513
|
-
return;
|
|
1514
|
-
}
|
|
1515
1500
|
uiLog.info("OpenAPI discover response:", openApiDevicesRaw);
|
|
1516
1501
|
discoveredDevices = mergeDiscoveredDevices(discoveredDevices, openApiDevicesRaw);
|
|
1517
1502
|
if (devicesFoundDisplay && discoveredDevices.length > 0) {
|
|
@@ -1591,9 +1576,6 @@ async function discoverDevices2() {
|
|
|
1591
1576
|
setDiscoveryCache(discoveredDevices);
|
|
1592
1577
|
updateLastScannedStatus();
|
|
1593
1578
|
} catch (e) {
|
|
1594
|
-
if (cancelled) {
|
|
1595
|
-
return;
|
|
1596
|
-
}
|
|
1597
1579
|
uiLog.error("Discovery error:", e);
|
|
1598
1580
|
status.textContent = `Error: ${e instanceof Error ? e.message : "Discovery failed"}`;
|
|
1599
1581
|
status.classList.add("error");
|
|
@@ -1618,11 +1600,6 @@ async function discoverDevices2() {
|
|
|
1618
1600
|
}
|
|
1619
1601
|
btn.disabled = false;
|
|
1620
1602
|
btn.textContent = "\u{1F50D} Discover Devices";
|
|
1621
|
-
if (cancelBtn) {
|
|
1622
|
-
cancelBtn.disabled = false;
|
|
1623
|
-
cancelBtn.style.display = "none";
|
|
1624
|
-
cancelBtn.onclick = null;
|
|
1625
|
-
}
|
|
1626
1603
|
}
|
|
1627
1604
|
}
|
|
1628
1605
|
async function updateDiscoveryView(allDevices, preferences, groupBy, hideAdded, selectedIds) {
|
|
@@ -2750,6 +2727,21 @@ __export(render_exports, {
|
|
|
2750
2727
|
setDiscoveryPreferences: () => setDiscoveryPreferences,
|
|
2751
2728
|
sortDevices: () => sortDevices
|
|
2752
2729
|
});
|
|
2730
|
+
async function copyTextWithFallback(text) {
|
|
2731
|
+
try {
|
|
2732
|
+
await navigator.clipboard.writeText(text);
|
|
2733
|
+
} catch {
|
|
2734
|
+
const textarea = document.createElement("textarea");
|
|
2735
|
+
textarea.value = text;
|
|
2736
|
+
textarea.setAttribute("readonly", "");
|
|
2737
|
+
textarea.style.cssText = "position:fixed;left:-9999px;opacity:0;pointer-events:none";
|
|
2738
|
+
document.body.appendChild(textarea);
|
|
2739
|
+
textarea.select();
|
|
2740
|
+
textarea.setSelectionRange(0, textarea.value.length);
|
|
2741
|
+
document.execCommand("copy");
|
|
2742
|
+
textarea.remove();
|
|
2743
|
+
}
|
|
2744
|
+
}
|
|
2753
2745
|
function getRssiSignalQuality(rssi) {
|
|
2754
2746
|
if (!rssi || rssi === 0) {
|
|
2755
2747
|
return {
|
|
@@ -2830,7 +2822,6 @@ function renderSignalQualityBadge(rssi) {
|
|
|
2830
2822
|
border-radius: 3px;
|
|
2831
2823
|
font-size: 10px;
|
|
2832
2824
|
font-weight: 600;
|
|
2833
|
-
margin-left: 8px;
|
|
2834
2825
|
`;
|
|
2835
2826
|
badge.title = quality.description;
|
|
2836
2827
|
return badge;
|
|
@@ -3475,6 +3466,7 @@ function renderDeviceList(list) {
|
|
|
3475
3466
|
}
|
|
3476
3467
|
status.textContent = `Found ${list.length} device(s)`;
|
|
3477
3468
|
ul.classList.add("device-grid");
|
|
3469
|
+
ul.style.padding = "0";
|
|
3478
3470
|
ul.innerHTML = "";
|
|
3479
3471
|
if (removeAllContainer) {
|
|
3480
3472
|
removeAllContainer.style.display = "block";
|
|
@@ -3486,6 +3478,7 @@ function renderDeviceList(list) {
|
|
|
3486
3478
|
li.style.display = "flex";
|
|
3487
3479
|
li.style.flexDirection = "column";
|
|
3488
3480
|
li.style.alignItems = "stretch";
|
|
3481
|
+
li.style.padding = "5px 8px";
|
|
3489
3482
|
li.style.marginBottom = "0";
|
|
3490
3483
|
const info = document.createElement("div");
|
|
3491
3484
|
info.style.flex = "1 1 auto";
|
|
@@ -3493,13 +3486,14 @@ function renderDeviceList(list) {
|
|
|
3493
3486
|
info.style.minWidth = "0";
|
|
3494
3487
|
const nameContainer = document.createElement("div");
|
|
3495
3488
|
nameContainer.style.display = "flex";
|
|
3496
|
-
nameContainer.style.
|
|
3497
|
-
nameContainer.style.
|
|
3498
|
-
nameContainer.style.
|
|
3489
|
+
nameContainer.style.alignItems = "center";
|
|
3490
|
+
nameContainer.style.marginBottom = "0";
|
|
3491
|
+
nameContainer.style.flexWrap = "wrap";
|
|
3492
|
+
nameContainer.style.gap = "4px";
|
|
3499
3493
|
const name = document.createElement("div");
|
|
3500
3494
|
name.style.fontWeight = "500";
|
|
3501
3495
|
name.style.fontSize = "13px";
|
|
3502
|
-
name.textContent = d.name || d.id;
|
|
3496
|
+
name.textContent = d.configDeviceName || d.name || d.id;
|
|
3503
3497
|
const expandedDetails = document.createElement("div");
|
|
3504
3498
|
expandedDetails.style.display = "none";
|
|
3505
3499
|
expandedDetails.appendChild(renderDeviceDetailsPanel(d));
|
|
@@ -3517,36 +3511,23 @@ function renderDeviceList(list) {
|
|
|
3517
3511
|
expandedDetails.style.display = isHidden ? "block" : "none";
|
|
3518
3512
|
expandBtn.style.transform = isHidden ? "rotate(180deg)" : "rotate(0deg)";
|
|
3519
3513
|
};
|
|
3520
|
-
|
|
3521
|
-
|
|
3522
|
-
code.style.fontSize = "10px";
|
|
3523
|
-
code.style.opacity = "0.75";
|
|
3524
|
-
code.style.marginLeft = "0";
|
|
3525
|
-
code.style.whiteSpace = "normal";
|
|
3526
|
-
code.style.overflowWrap = "anywhere";
|
|
3527
|
-
code.style.wordBreak = "break-word";
|
|
3528
|
-
code.style.maxWidth = "100%";
|
|
3529
|
-
const headerRow = document.createElement("div");
|
|
3530
|
-
headerRow.style.display = "inline-flex";
|
|
3531
|
-
headerRow.style.alignItems = "center";
|
|
3532
|
-
headerRow.style.gap = "4px";
|
|
3533
|
-
headerRow.appendChild(name);
|
|
3534
|
-
headerRow.appendChild(expandBtn);
|
|
3535
|
-
nameContainer.appendChild(headerRow);
|
|
3536
|
-
nameContainer.appendChild(code);
|
|
3514
|
+
nameContainer.appendChild(name);
|
|
3515
|
+
nameContainer.appendChild(expandBtn);
|
|
3537
3516
|
if (d.rssi !== void 0 && d.rssi !== null && d.rssi !== 0) {
|
|
3538
3517
|
nameContainer.appendChild(renderSignalBars(d.rssi));
|
|
3539
3518
|
nameContainer.appendChild(renderSignalQualityBadge(d.rssi));
|
|
3540
3519
|
}
|
|
3541
3520
|
const meta = document.createElement("div");
|
|
3542
|
-
meta.style.opacity = "0.
|
|
3543
|
-
meta.style.
|
|
3544
|
-
meta.style.
|
|
3545
|
-
const
|
|
3546
|
-
const
|
|
3521
|
+
meta.style.opacity = "0.7";
|
|
3522
|
+
meta.style.fontSize = "10px";
|
|
3523
|
+
meta.style.fontFamily = "monospace";
|
|
3524
|
+
const deviceIdentifier = d.deviceId || d.id;
|
|
3525
|
+
const id = `ID: ${deviceIdentifier}`;
|
|
3526
|
+
const typeText = d.configDeviceType || d.type ? `Type: ${d.configDeviceType || d.type}` : "";
|
|
3527
|
+
const connText = d.connectionPreference ? `Conn: ${d.connectionPreference}` : "";
|
|
3547
3528
|
const extText = d.externalPublishProtocol && d.externalPublishProtocol !== "none" ? `external: ${d.externalPublishProtocol}` : "";
|
|
3548
|
-
const roomText = d.room ? `
|
|
3549
|
-
meta.textContent = [typeText, connText, extText, roomText].filter(Boolean).join(" | ");
|
|
3529
|
+
const roomText = d.room ? `Room: ${d.room}` : "";
|
|
3530
|
+
meta.textContent = [id, typeText, connText, extText, roomText].filter(Boolean).join(" | ");
|
|
3550
3531
|
info.appendChild(nameContainer);
|
|
3551
3532
|
info.appendChild(meta);
|
|
3552
3533
|
info.appendChild(expandedDetails);
|
|
@@ -3573,7 +3554,9 @@ function renderDeviceList(list) {
|
|
|
3573
3554
|
copyBtn.style.fontSize = "11px";
|
|
3574
3555
|
copyBtn.addEventListener("click", async () => {
|
|
3575
3556
|
try {
|
|
3576
|
-
|
|
3557
|
+
if (deviceIdentifier) {
|
|
3558
|
+
await copyTextWithFallback(deviceIdentifier);
|
|
3559
|
+
}
|
|
3577
3560
|
copyBtn.textContent = "Copied";
|
|
3578
3561
|
copyBtn.classList.add("success");
|
|
3579
3562
|
setTimeout(() => {
|
|
@@ -3600,8 +3583,8 @@ function renderDeviceList(list) {
|
|
|
3600
3583
|
};
|
|
3601
3584
|
buttons.appendChild(editBtn);
|
|
3602
3585
|
buttons.appendChild(copyBtn);
|
|
3603
|
-
buttons.appendChild(createConnectionTestControls(d));
|
|
3604
3586
|
buttons.appendChild(deleteBtn);
|
|
3587
|
+
buttons.appendChild(createConnectionTestControls(d));
|
|
3605
3588
|
li.appendChild(info);
|
|
3606
3589
|
li.appendChild(buttons);
|
|
3607
3590
|
ul.appendChild(li);
|