simvyn 2.0.0 → 2.2.0
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/dashboard/assets/{index-Pv0mHRGr.css → index-B6SC-KfX.css} +44 -2
- package/dist/dashboard/assets/{index-SgS9nwZ7.js → index-B_mApJSj.js} +185 -13
- package/dist/dashboard/assets/index-B_mApJSj.js.map +1 -0
- package/dist/dashboard/index.html +2 -2
- package/dist/index.js +153 -44
- package/package.json +1 -1
- package/dist/dashboard/assets/index-SgS9nwZ7.js.map +0 -1
|
@@ -471,6 +471,10 @@
|
|
|
471
471
|
z-index: 50;
|
|
472
472
|
}
|
|
473
473
|
|
|
474
|
+
.z-\[100\] {
|
|
475
|
+
z-index: 100;
|
|
476
|
+
}
|
|
477
|
+
|
|
474
478
|
.col-span-2 {
|
|
475
479
|
grid-column: span 2 / span 2;
|
|
476
480
|
}
|
|
@@ -776,8 +780,8 @@
|
|
|
776
780
|
width: calc(var(--spacing) * 48);
|
|
777
781
|
}
|
|
778
782
|
|
|
779
|
-
.w-
|
|
780
|
-
width: calc(var(--spacing) *
|
|
783
|
+
.w-84 {
|
|
784
|
+
width: calc(var(--spacing) * 84);
|
|
781
785
|
}
|
|
782
786
|
|
|
783
787
|
.w-\[30\%\] {
|
|
@@ -1314,6 +1318,10 @@
|
|
|
1314
1318
|
background-color: #1e1e2d99 !important;
|
|
1315
1319
|
}
|
|
1316
1320
|
|
|
1321
|
+
.\!bg-\[rgba\(30\,30\,45\,0\.85\)\] {
|
|
1322
|
+
background-color: #1e1e2dd9 !important;
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1317
1325
|
.bg-accent-blue {
|
|
1318
1326
|
background-color: var(--color-accent-blue);
|
|
1319
1327
|
}
|
|
@@ -1542,6 +1550,10 @@
|
|
|
1542
1550
|
}
|
|
1543
1551
|
}
|
|
1544
1552
|
|
|
1553
|
+
.fill-amber-400 {
|
|
1554
|
+
fill: var(--color-amber-400);
|
|
1555
|
+
}
|
|
1556
|
+
|
|
1545
1557
|
.object-cover {
|
|
1546
1558
|
object-fit: cover;
|
|
1547
1559
|
}
|
|
@@ -1865,6 +1877,16 @@
|
|
|
1865
1877
|
color: var(--color-text-muted);
|
|
1866
1878
|
}
|
|
1867
1879
|
|
|
1880
|
+
.text-text-muted\/40 {
|
|
1881
|
+
color: #54555866;
|
|
1882
|
+
}
|
|
1883
|
+
|
|
1884
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1885
|
+
.text-text-muted\/40 {
|
|
1886
|
+
color: color-mix(in oklab, var(--color-text-muted) 40%, transparent);
|
|
1887
|
+
}
|
|
1888
|
+
}
|
|
1889
|
+
|
|
1868
1890
|
.text-text-muted\/50 {
|
|
1869
1891
|
color: #54555880;
|
|
1870
1892
|
}
|
|
@@ -1944,6 +1966,16 @@
|
|
|
1944
1966
|
}
|
|
1945
1967
|
}
|
|
1946
1968
|
|
|
1969
|
+
.shadow-black\/40 {
|
|
1970
|
+
--tw-shadow-color: #0006;
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1973
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
1974
|
+
.shadow-black\/40 {
|
|
1975
|
+
--tw-shadow-color: color-mix(in oklab, color-mix(in oklab, var(--color-black) 40%, transparent) var(--tw-shadow-alpha), transparent);
|
|
1976
|
+
}
|
|
1977
|
+
}
|
|
1978
|
+
|
|
1947
1979
|
.ring-green-500\/20 {
|
|
1948
1980
|
--tw-ring-color: #00c75833;
|
|
1949
1981
|
}
|
|
@@ -2103,6 +2135,16 @@
|
|
|
2103
2135
|
}
|
|
2104
2136
|
}
|
|
2105
2137
|
|
|
2138
|
+
.hover\:text-amber-400\/60:hover {
|
|
2139
|
+
color: #fcbb0099;
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2142
|
+
@supports (color: color-mix(in lab, red, red)) {
|
|
2143
|
+
.hover\:text-amber-400\/60:hover {
|
|
2144
|
+
color: color-mix(in oklab, var(--color-amber-400) 60%, transparent);
|
|
2145
|
+
}
|
|
2146
|
+
}
|
|
2147
|
+
|
|
2106
2148
|
.hover\:text-red-200:hover {
|
|
2107
2149
|
color: var(--color-red-200);
|
|
2108
2150
|
}
|
|
@@ -30173,6 +30173,46 @@ function useWsListener(channel, type, handler) {
|
|
|
30173
30173
|
return addListener(channel, type, handler);
|
|
30174
30174
|
}, [addListener, channel, type, handler]);
|
|
30175
30175
|
}
|
|
30176
|
+
const useFavouriteStore = create((set, get2) => ({
|
|
30177
|
+
favouriteIds: /* @__PURE__ */ new Set(),
|
|
30178
|
+
loaded: false,
|
|
30179
|
+
load: async () => {
|
|
30180
|
+
try {
|
|
30181
|
+
const res = await fetch("/api/modules/devices/favourites");
|
|
30182
|
+
if (res.ok) {
|
|
30183
|
+
const data = await res.json();
|
|
30184
|
+
const ids = data.favourites ?? [];
|
|
30185
|
+
set({ favouriteIds: new Set(ids), loaded: true });
|
|
30186
|
+
}
|
|
30187
|
+
} catch {
|
|
30188
|
+
}
|
|
30189
|
+
},
|
|
30190
|
+
toggle: async (id2) => {
|
|
30191
|
+
const { favouriteIds } = get2();
|
|
30192
|
+
const wasFavourite = favouriteIds.has(id2);
|
|
30193
|
+
const next = new Set(favouriteIds);
|
|
30194
|
+
if (wasFavourite) {
|
|
30195
|
+
next.delete(id2);
|
|
30196
|
+
} else {
|
|
30197
|
+
next.add(id2);
|
|
30198
|
+
}
|
|
30199
|
+
set({ favouriteIds: next });
|
|
30200
|
+
try {
|
|
30201
|
+
const res = await fetch("/api/modules/devices/favourites", {
|
|
30202
|
+
method: wasFavourite ? "DELETE" : "POST",
|
|
30203
|
+
headers: { "Content-Type": "application/json" },
|
|
30204
|
+
body: JSON.stringify({ deviceId: id2 })
|
|
30205
|
+
});
|
|
30206
|
+
if (!res.ok) {
|
|
30207
|
+
set({ favouriteIds });
|
|
30208
|
+
}
|
|
30209
|
+
} catch {
|
|
30210
|
+
set({ favouriteIds });
|
|
30211
|
+
}
|
|
30212
|
+
},
|
|
30213
|
+
isFavourite: (id2) => get2().favouriteIds.has(id2)
|
|
30214
|
+
}));
|
|
30215
|
+
useFavouriteStore.getState().load();
|
|
30176
30216
|
const MULTI_SELECT_MODULES = /* @__PURE__ */ new Set(["location"]);
|
|
30177
30217
|
function groupDevices(devices) {
|
|
30178
30218
|
const groups = {};
|
|
@@ -30193,22 +30233,52 @@ function groupDevices(devices) {
|
|
|
30193
30233
|
}
|
|
30194
30234
|
return ordered;
|
|
30195
30235
|
}
|
|
30236
|
+
function StarIcon({
|
|
30237
|
+
filled,
|
|
30238
|
+
onClick
|
|
30239
|
+
}) {
|
|
30240
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
30241
|
+
"svg",
|
|
30242
|
+
{
|
|
30243
|
+
className: `h-3.5 w-3.5 shrink-0 cursor-pointer transition-colors ${filled ? "text-amber-400" : "text-text-muted/40 hover:text-amber-400/60"}`,
|
|
30244
|
+
viewBox: "0 0 24 24",
|
|
30245
|
+
fill: filled ? "currentColor" : "none",
|
|
30246
|
+
stroke: "currentColor",
|
|
30247
|
+
strokeWidth: 2,
|
|
30248
|
+
onClick,
|
|
30249
|
+
children: [
|
|
30250
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("title", { children: filled ? "Remove from Favourites" : "Add to Favourites" }),
|
|
30251
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
30252
|
+
"path",
|
|
30253
|
+
{
|
|
30254
|
+
strokeLinecap: "round",
|
|
30255
|
+
strokeLinejoin: "round",
|
|
30256
|
+
d: "M11.48 3.499a.562.562 0 011.04 0l2.125 5.111a.563.563 0 00.475.345l5.518.442c.499.04.701.663.321.988l-4.204 3.602a.563.563 0 00-.182.557l1.285 5.385a.562.562 0 01-.84.61l-4.725-2.885a.563.563 0 00-.586 0L6.982 20.54a.562.562 0 01-.84-.61l1.285-5.386a.562.562 0 00-.182-.557l-4.204-3.602a.563.563 0 01.321-.988l5.518-.442a.563.563 0 00.475-.345L11.48 3.5z"
|
|
30257
|
+
}
|
|
30258
|
+
)
|
|
30259
|
+
]
|
|
30260
|
+
}
|
|
30261
|
+
);
|
|
30262
|
+
}
|
|
30196
30263
|
function StateIndicator({ state }) {
|
|
30197
30264
|
return /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
30198
30265
|
"span",
|
|
30199
30266
|
{
|
|
30200
|
-
className: `inline-block h-2 w-2 rounded-full ${state === "booted" ? "bg-green-500 ring-2 ring-green-500/20" : "bg-text-muted/50"}`
|
|
30267
|
+
className: `inline-block h-2 w-2 shrink-0 rounded-full ${state === "booted" ? "bg-green-500 ring-2 ring-green-500/20" : "bg-text-muted/50"}`
|
|
30201
30268
|
}
|
|
30202
30269
|
);
|
|
30203
30270
|
}
|
|
30204
30271
|
function DeviceSelector() {
|
|
30205
30272
|
const [open, setOpen] = reactExports.useState(false);
|
|
30273
|
+
const [contextMenu, setContextMenu] = reactExports.useState(null);
|
|
30206
30274
|
const ref = reactExports.useRef(null);
|
|
30207
30275
|
const devices = useDeviceStore((s) => s.devices);
|
|
30208
30276
|
const selectedDeviceIds = useDeviceStore((s) => s.selectedDeviceIds);
|
|
30209
30277
|
const selectDevice = useDeviceStore((s) => s.selectDevice);
|
|
30210
30278
|
const toggleDevice = useDeviceStore((s) => s.toggleDevice);
|
|
30211
30279
|
const truncateToFirst = useDeviceStore((s) => s.truncateToFirst);
|
|
30280
|
+
const toggleFavourite = useFavouriteStore((s) => s.toggle);
|
|
30281
|
+
const isFavourite = useFavouriteStore((s) => s.isFavourite);
|
|
30212
30282
|
const activeModule = useModuleStore((s) => s.activeModule);
|
|
30213
30283
|
const isMultiSelect = MULTI_SELECT_MODULES.has(activeModule ?? "");
|
|
30214
30284
|
const handleDeviceDisconnected = reactExports.useCallback((payload) => {
|
|
@@ -30226,11 +30296,24 @@ function DeviceSelector() {
|
|
|
30226
30296
|
function handleClick(e) {
|
|
30227
30297
|
if (ref.current && !ref.current.contains(e.target)) {
|
|
30228
30298
|
setOpen(false);
|
|
30299
|
+
setContextMenu(null);
|
|
30229
30300
|
}
|
|
30230
30301
|
}
|
|
30231
30302
|
document.addEventListener("mousedown", handleClick);
|
|
30232
30303
|
return () => document.removeEventListener("mousedown", handleClick);
|
|
30233
30304
|
}, []);
|
|
30305
|
+
reactExports.useEffect(() => {
|
|
30306
|
+
if (!contextMenu) return;
|
|
30307
|
+
function handleClick() {
|
|
30308
|
+
setContextMenu(null);
|
|
30309
|
+
}
|
|
30310
|
+
document.addEventListener("mousedown", handleClick);
|
|
30311
|
+
return () => document.removeEventListener("mousedown", handleClick);
|
|
30312
|
+
}, [contextMenu]);
|
|
30313
|
+
const handleContextMenu = (e, deviceId) => {
|
|
30314
|
+
e.preventDefault();
|
|
30315
|
+
setContextMenu({ x: e.clientX, y: e.clientY, deviceId });
|
|
30316
|
+
};
|
|
30234
30317
|
const selectedSet = new Set(selectedDeviceIds);
|
|
30235
30318
|
const firstDevice = devices.find((d) => d.id === selectedDeviceIds[0]);
|
|
30236
30319
|
let label;
|
|
@@ -30266,7 +30349,7 @@ function DeviceSelector() {
|
|
|
30266
30349
|
]
|
|
30267
30350
|
}
|
|
30268
30351
|
),
|
|
30269
|
-
open && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "glass-panel absolute top-full right-0 z-50 mt-2 w-
|
|
30352
|
+
open && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "glass-panel absolute top-full right-0 z-50 mt-2 w-84 max-h-96 overflow-y-auto p-1 shadow-xl shadow-black/30 !backdrop-blur-2xl !bg-[rgba(30,30,45,0.6)]", children: [
|
|
30270
30353
|
Object.entries(groups).map(([platform, devs]) => /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
30271
30354
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-3 py-1 text-[10px] font-semibold uppercase tracking-wider text-text-muted", children: platform }),
|
|
30272
30355
|
devs.map((d) => {
|
|
@@ -30283,24 +30366,32 @@ function DeviceSelector() {
|
|
|
30283
30366
|
setOpen(false);
|
|
30284
30367
|
}
|
|
30285
30368
|
},
|
|
30369
|
+
onContextMenu: (e) => handleContextMenu(e, d.id),
|
|
30286
30370
|
className: `flex w-full items-center gap-2 rounded-[var(--radius-button)] px-3 py-2 text-left text-sm transition-colors ${isSelected ? "bg-accent-blue/20 text-accent-blue" : "text-text-primary hover:bg-[rgba(255,255,255,0.08)]"}`,
|
|
30287
30371
|
children: [
|
|
30288
30372
|
isMultiSelect ? /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
30289
30373
|
"span",
|
|
30290
30374
|
{
|
|
30291
|
-
className: `inline-flex h-3.5 w-3.5 items-center justify-center rounded-full border ${isSelected ? "border-accent-blue bg-accent-blue" : "border-text-muted/50 bg-transparent"}`,
|
|
30375
|
+
className: `inline-flex h-3.5 w-3.5 shrink-0 items-center justify-center rounded-full border ${isSelected ? "border-accent-blue bg-accent-blue" : "border-text-muted/50 bg-transparent"}`,
|
|
30292
30376
|
children: isSelected && /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "h-1.5 w-1.5 rounded-full bg-white" })
|
|
30293
30377
|
}
|
|
30294
30378
|
) : /* @__PURE__ */ jsxRuntimeExports.jsx(StateIndicator, { state: d.state }),
|
|
30295
|
-
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 truncate", children: d.name }),
|
|
30296
|
-
/* @__PURE__ */ jsxRuntimeExports.
|
|
30297
|
-
|
|
30298
|
-
|
|
30299
|
-
|
|
30379
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "flex-1 truncate", title: d.name, children: d.name }),
|
|
30380
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "shrink-0 text-xs text-text-muted", children: d.osVersion }),
|
|
30381
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
30382
|
+
StarIcon,
|
|
30383
|
+
{
|
|
30384
|
+
filled: isFavourite(d.id),
|
|
30385
|
+
onClick: (e) => {
|
|
30386
|
+
e.stopPropagation();
|
|
30387
|
+
toggleFavourite(d.id);
|
|
30388
|
+
}
|
|
30389
|
+
}
|
|
30390
|
+
),
|
|
30300
30391
|
!isMultiSelect && isSelected && /* @__PURE__ */ jsxRuntimeExports.jsxs(
|
|
30301
30392
|
"svg",
|
|
30302
30393
|
{
|
|
30303
|
-
className: "h-4 w-4 text-accent-blue",
|
|
30394
|
+
className: "h-4 w-4 shrink-0 text-accent-blue",
|
|
30304
30395
|
fill: "none",
|
|
30305
30396
|
viewBox: "0 0 24 24",
|
|
30306
30397
|
stroke: "currentColor",
|
|
@@ -30325,7 +30416,27 @@ function DeviceSelector() {
|
|
|
30325
30416
|
})
|
|
30326
30417
|
] }, platform)),
|
|
30327
30418
|
devices.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "px-3 py-4 text-center text-sm text-text-muted", children: "No devices detected" })
|
|
30328
|
-
] })
|
|
30419
|
+
] }),
|
|
30420
|
+
contextMenu && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
30421
|
+
"div",
|
|
30422
|
+
{
|
|
30423
|
+
className: "glass-panel fixed p-1 shadow-xl shadow-black/40 z-[100] !backdrop-blur-2xl !bg-[rgba(30,30,45,0.85)]",
|
|
30424
|
+
style: { left: contextMenu.x, top: contextMenu.y },
|
|
30425
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
30426
|
+
"button",
|
|
30427
|
+
{
|
|
30428
|
+
type: "button",
|
|
30429
|
+
className: "flex w-full items-center gap-2 rounded-[var(--radius-button)] px-3 py-1.5 text-left text-sm text-text-primary hover:bg-[rgba(255,255,255,0.08)] whitespace-nowrap",
|
|
30430
|
+
onMouseDown: (e) => {
|
|
30431
|
+
e.stopPropagation();
|
|
30432
|
+
toggleFavourite(contextMenu.deviceId);
|
|
30433
|
+
setContextMenu(null);
|
|
30434
|
+
},
|
|
30435
|
+
children: isFavourite(contextMenu.deviceId) ? "Remove from Favourites" : "Add to Favourites"
|
|
30436
|
+
}
|
|
30437
|
+
)
|
|
30438
|
+
}
|
|
30439
|
+
)
|
|
30329
30440
|
] });
|
|
30330
30441
|
}
|
|
30331
30442
|
function isMac() {
|
|
@@ -30485,6 +30596,8 @@ function DevicePanel() {
|
|
|
30485
30596
|
} catch {
|
|
30486
30597
|
}
|
|
30487
30598
|
}
|
|
30599
|
+
const favouriteIds = useFavouriteStore((s) => s.favouriteIds);
|
|
30600
|
+
const favouriteDevices = devices.filter((d) => favouriteIds.has(d.id));
|
|
30488
30601
|
const iosDevices = devices.filter((d) => d.platform === "ios");
|
|
30489
30602
|
const androidDevices = devices.filter((d) => d.platform === "android");
|
|
30490
30603
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-6 space-y-6", children: [
|
|
@@ -30508,6 +30621,17 @@ function DevicePanel() {
|
|
|
30508
30621
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-base font-medium text-text-primary mb-2", children: "No Devices Detected" }),
|
|
30509
30622
|
/* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "text-sm text-text-secondary", children: "Make sure Xcode Simulator or Android Emulator tools are installed." })
|
|
30510
30623
|
] }),
|
|
30624
|
+
favouriteDevices.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
30625
|
+
FavouritesSection,
|
|
30626
|
+
{
|
|
30627
|
+
devices: favouriteDevices,
|
|
30628
|
+
actionInFlight,
|
|
30629
|
+
onAction: doAction,
|
|
30630
|
+
onClone: handleClone,
|
|
30631
|
+
onRename: handleRename,
|
|
30632
|
+
onDelete: handleDelete
|
|
30633
|
+
}
|
|
30634
|
+
),
|
|
30511
30635
|
iosDevices.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
30512
30636
|
IosDeviceSection,
|
|
30513
30637
|
{
|
|
@@ -30629,6 +30753,35 @@ function CreateSimulatorForm({ onCreated }) {
|
|
|
30629
30753
|
] })
|
|
30630
30754
|
] });
|
|
30631
30755
|
}
|
|
30756
|
+
function FavouritesSection({
|
|
30757
|
+
devices,
|
|
30758
|
+
actionInFlight,
|
|
30759
|
+
onAction,
|
|
30760
|
+
onClone,
|
|
30761
|
+
onRename,
|
|
30762
|
+
onDelete
|
|
30763
|
+
}) {
|
|
30764
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
|
|
30765
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 mb-3", children: [
|
|
30766
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(Star, { size: 14, className: "text-amber-400", fill: "currentColor" }),
|
|
30767
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-sm font-medium text-text-muted uppercase tracking-wider", children: "Favourites" })
|
|
30768
|
+
] }),
|
|
30769
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "grid gap-3 grid-cols-1 sm:grid-cols-2 lg:grid-cols-3", children: devices.map((device) => /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
30770
|
+
DeviceCard,
|
|
30771
|
+
{
|
|
30772
|
+
device,
|
|
30773
|
+
isLoading: actionInFlight?.deviceId === device.id,
|
|
30774
|
+
loadingAction: actionInFlight?.deviceId === device.id ? actionInFlight.action : void 0,
|
|
30775
|
+
onAction,
|
|
30776
|
+
onClone: device.platform === "ios" ? () => onClone(device) : void 0,
|
|
30777
|
+
onRename: device.platform === "ios" ? () => onRename(device) : void 0,
|
|
30778
|
+
onDelete: device.platform === "ios" ? () => onDelete(device) : void 0,
|
|
30779
|
+
showLifecycleActions: device.platform === "ios"
|
|
30780
|
+
},
|
|
30781
|
+
device.id
|
|
30782
|
+
)) })
|
|
30783
|
+
] });
|
|
30784
|
+
}
|
|
30632
30785
|
function IosDeviceSection({
|
|
30633
30786
|
devices,
|
|
30634
30787
|
actionInFlight,
|
|
@@ -30872,13 +31025,32 @@ function DeviceCard({
|
|
|
30872
31025
|
onDelete,
|
|
30873
31026
|
showLifecycleActions
|
|
30874
31027
|
}) {
|
|
31028
|
+
const isFav = useFavouriteStore((s) => s.isFavourite)(device.id);
|
|
31029
|
+
const toggleFavourite = useFavouriteStore((s) => s.toggle);
|
|
30875
31030
|
const truncatedId = device.id.length > 16 ? `${device.id.slice(0, 8)}…${device.id.slice(-6)}` : device.id;
|
|
30876
31031
|
return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "glass-panel p-4 flex flex-col gap-3 hover:border-glass-border-hover transition-all duration-150", children: [
|
|
30877
|
-
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between", children: [
|
|
31032
|
+
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
30878
31033
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
30879
31034
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "font-medium text-text-primary truncate", children: device.name }),
|
|
30880
31035
|
/* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-xs text-text-muted mt-0.5 font-mono", children: truncatedId })
|
|
30881
31036
|
] }),
|
|
31037
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
31038
|
+
"button",
|
|
31039
|
+
{
|
|
31040
|
+
type: "button",
|
|
31041
|
+
onClick: () => toggleFavourite(device.id),
|
|
31042
|
+
className: "shrink-0 mt-0.5",
|
|
31043
|
+
title: isFav ? "Remove from Favourites" : "Add to Favourites",
|
|
31044
|
+
children: /* @__PURE__ */ jsxRuntimeExports.jsx(
|
|
31045
|
+
Star,
|
|
31046
|
+
{
|
|
31047
|
+
size: 16,
|
|
31048
|
+
className: `transition-colors cursor-pointer ${isFav ? "text-amber-400 fill-amber-400" : "text-text-muted/40 hover:text-amber-400/60"}`,
|
|
31049
|
+
fill: isFav ? "currentColor" : "none"
|
|
31050
|
+
}
|
|
31051
|
+
)
|
|
31052
|
+
}
|
|
31053
|
+
),
|
|
30882
31054
|
/* @__PURE__ */ jsxRuntimeExports.jsx(StateBadge, { state: device.state })
|
|
30883
31055
|
] }),
|
|
30884
31056
|
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-3 text-xs text-text-secondary", children: [
|
|
@@ -51520,7 +51692,7 @@ function ToolSettingsPanel() {
|
|
|
51520
51692
|
const [copied, setCopied] = reactExports.useState(false);
|
|
51521
51693
|
const devices = useDeviceStore((s) => s.devices);
|
|
51522
51694
|
const modules = useModuleStore((s) => s.modules);
|
|
51523
|
-
const version = "2.
|
|
51695
|
+
const version = "2.2.0";
|
|
51524
51696
|
const fetchStorage = reactExports.useCallback(() => {
|
|
51525
51697
|
fetch("/api/tool-settings/storage").then((r) => r.json()).then((data) => setStorage(data)).catch(() => {
|
|
51526
51698
|
});
|
|
@@ -52868,4 +53040,4 @@ function App() {
|
|
|
52868
53040
|
clientExports.createRoot(document.getElementById("root")).render(
|
|
52869
53041
|
/* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.StrictMode, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(App, {}) })
|
|
52870
53042
|
);
|
|
52871
|
-
//# sourceMappingURL=index-
|
|
53043
|
+
//# sourceMappingURL=index-B_mApJSj.js.map
|