react-os-shell 1.4.0 → 1.5.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/{Browser-L5CB7K7B.js → Browser-MYVYM7YM.js} +4 -4
- package/dist/{Browser-L5CB7K7B.js.map → Browser-MYVYM7YM.js.map} +1 -1
- package/dist/{Documents-3V4WI42V.js → Documents-SLODLCU4.js} +3 -3
- package/dist/{Documents-3V4WI42V.js.map → Documents-SLODLCU4.js.map} +1 -1
- package/dist/{Files-3R7EHNSF.js → Files-NE4YZTRX.js} +7 -7
- package/dist/{Files-3R7EHNSF.js.map → Files-NE4YZTRX.js.map} +1 -1
- package/dist/{Notepad-6V4JVBVJ.js → Notepad-F3TLHMWJ.js} +3 -3
- package/dist/{Notepad-6V4JVBVJ.js.map → Notepad-F3TLHMWJ.js.map} +1 -1
- package/dist/Preview-HFGTMXE7.js +9 -0
- package/dist/{Preview-BTFJ7A6T.js.map → Preview-HFGTMXE7.js.map} +1 -1
- package/dist/{Spreadsheet-UAYZUO4B.js → Spreadsheet-WF34DA44.js} +4 -4
- package/dist/{Spreadsheet-UAYZUO4B.js.map → Spreadsheet-WF34DA44.js.map} +1 -1
- package/dist/apps/index.js +12 -12
- package/dist/chunk-F6NIGZTF.js +262 -0
- package/dist/chunk-F6NIGZTF.js.map +1 -0
- package/dist/{chunk-T6TOGZ2V.js → chunk-IJ5Y4EGQ.js} +3 -3
- package/dist/{chunk-T6TOGZ2V.js.map → chunk-IJ5Y4EGQ.js.map} +1 -1
- package/dist/{chunk-CJH5U3BW.js → chunk-PTRHYPXO.js} +3 -3
- package/dist/{chunk-CJH5U3BW.js.map → chunk-PTRHYPXO.js.map} +1 -1
- package/dist/{chunk-2HWXLIAQ.js → chunk-RE2FEWBE.js} +138 -25
- package/dist/chunk-RE2FEWBE.js.map +1 -0
- package/dist/{chunk-EUP5PCNL.js → chunk-W5ARJ7PU.js} +5 -5
- package/dist/{chunk-EUP5PCNL.js.map → chunk-W5ARJ7PU.js.map} +1 -1
- package/dist/{chunk-5BZBQGMU.js → chunk-XHBHCL5I.js} +3 -3
- package/dist/{chunk-5BZBQGMU.js.map → chunk-XHBHCL5I.js.map} +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +85 -434
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/Preview-BTFJ7A6T.js +0 -9
- package/dist/chunk-2HWXLIAQ.js.map +0 -1
- package/dist/chunk-HBJUIVN3.js +0 -98
- package/dist/chunk-HBJUIVN3.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -4,18 +4,18 @@ import { subscribePomo, getPomoSnapshot } from './chunk-5X5LQNOX.js';
|
|
|
4
4
|
export { setShellTodoProvider } from './chunk-5X5LQNOX.js';
|
|
5
5
|
import { useShellPrefs } from './chunk-36VM54SC.js';
|
|
6
6
|
export { ShellPrefsProvider, useLocalStoragePrefs, useShellPrefs } from './chunk-36VM54SC.js';
|
|
7
|
-
import { PREVIEW_OPENED_EVENT, openPreviewFile } from './chunk-
|
|
8
|
-
export { Breadcrumbs } from './chunk-
|
|
7
|
+
import { PREVIEW_OPENED_EVENT, publishDesktopFolders, requestFilesTrashView, FolderGlyph, openPreviewFile, requestFilesDesktopFolderView, FileIconTile, hashGradient } from './chunk-F6NIGZTF.js';
|
|
8
|
+
export { Breadcrumbs } from './chunk-F6NIGZTF.js';
|
|
9
9
|
import { SidebarLayout } from './chunk-VGTEM5RZ.js';
|
|
10
10
|
export { SidebarLayout } from './chunk-VGTEM5RZ.js';
|
|
11
11
|
import { playNotification, playStartup, soundsEnabled, getSoundConfig, SOUND_PACK_KEYS, SOUND_PACKS, SOUND_TYPES, SOUND_TYPE_LABELS, setSoundForType, previewSound, setAllSounds, playLogout } from './chunk-D7PYW2QS.js';
|
|
12
|
-
import { setPdfPreview } from './chunk-
|
|
12
|
+
import { setPdfPreview } from './chunk-PTRHYPXO.js';
|
|
13
13
|
import './chunk-KUIPWCTJ.js';
|
|
14
14
|
import { toast_default } from './chunk-WIJ45SYD.js';
|
|
15
15
|
export { toast_default as toast } from './chunk-WIJ45SYD.js';
|
|
16
|
-
export { EditableGrid } from './chunk-
|
|
17
|
-
import { APP_VERSION } from './chunk-
|
|
18
|
-
export { VERSION } from './chunk-
|
|
16
|
+
export { EditableGrid } from './chunk-IJ5Y4EGQ.js';
|
|
17
|
+
import { APP_VERSION } from './chunk-W5ARJ7PU.js';
|
|
18
|
+
export { VERSION } from './chunk-W5ARJ7PU.js';
|
|
19
19
|
import { useWindowManager, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, WINDOW_REGISTRY, isPageEntry, useIsMobile, ModalActions, useModalActive, client_default, LoadingSpinner, setWindowPosition, ThumbCard, activateModal } from './chunk-GWVVILYQ.js';
|
|
20
20
|
export { CancelButton, CopyButton, DocFavStar, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, WindowManagerProvider, WindowTitle, commitExposeHighlight, exitExposeMode, getActiveWindowRoute, getExposeHighlight, getWindowPosition, isEntityEntry, isPageEntry, setExposeHighlight, setShellApiClient, setShellWindowRegistry, setWindowDefaultPosition, setWindowPosition, subscribeExposeHighlight, toggleExposeMode, useModalActive, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-GWVVILYQ.js';
|
|
21
21
|
import { confirm } from './chunk-UBN4IUDE.js';
|
|
@@ -1488,87 +1488,8 @@ async function reportBug(submit) {
|
|
|
1488
1488
|
toast_default.error(err?.response?.data?.detail || "Failed to send.");
|
|
1489
1489
|
}
|
|
1490
1490
|
}
|
|
1491
|
-
var ENTITY_ICON_COLORS = {
|
|
1492
|
-
order: "text-blue-600",
|
|
1493
|
-
purchase_order: "text-purple-600",
|
|
1494
|
-
invoice: "text-green-600",
|
|
1495
|
-
client: "text-indigo-600",
|
|
1496
|
-
manufacturer: "text-orange-600",
|
|
1497
|
-
shipment: "text-teal-600",
|
|
1498
|
-
part_number: "text-gray-600",
|
|
1499
|
-
project: "text-pink-600",
|
|
1500
|
-
mould: "text-red-600",
|
|
1501
|
-
design: "text-cyan-600",
|
|
1502
|
-
brand: "text-amber-600",
|
|
1503
|
-
price_sheet: "text-emerald-600",
|
|
1504
|
-
folder: "text-yellow-600",
|
|
1505
|
-
page: "text-blue-500"
|
|
1506
|
-
};
|
|
1507
|
-
var ENTITY_ICONS = {
|
|
1508
|
-
order: "SO",
|
|
1509
|
-
purchase_order: "PO",
|
|
1510
|
-
invoice: "INV",
|
|
1511
|
-
client: "CLI",
|
|
1512
|
-
manufacturer: "MFR",
|
|
1513
|
-
shipment: "DN",
|
|
1514
|
-
part_number: "PN",
|
|
1515
|
-
project: "PRJ",
|
|
1516
|
-
mould: "MLD",
|
|
1517
|
-
design: "DSN",
|
|
1518
|
-
brand: "BRD",
|
|
1519
|
-
price_sheet: "PS",
|
|
1520
|
-
vendor_invoice: "VI",
|
|
1521
|
-
vendor_payment: "VP",
|
|
1522
|
-
warranty_claim: "WC",
|
|
1523
|
-
qc_report: "QC",
|
|
1524
|
-
vendor_shipment: "GRN",
|
|
1525
|
-
bank_account: "BA",
|
|
1526
|
-
wheel_finish: "WF",
|
|
1527
|
-
weight_log: "WL",
|
|
1528
|
-
production_progress: "PP",
|
|
1529
|
-
vendor_price_sheet: "VPS",
|
|
1530
|
-
proposal: "PR",
|
|
1531
|
-
folder: "FLD"
|
|
1532
|
-
};
|
|
1533
|
-
var PREVIEW_FILE_CODES = {
|
|
1534
|
-
pdf: "PDF",
|
|
1535
|
-
dxf: "DXF",
|
|
1536
|
-
"3d": "STP",
|
|
1537
|
-
image: "IMG",
|
|
1538
|
-
csv: "CSV"
|
|
1539
|
-
};
|
|
1540
|
-
var PREVIEW_FILE_COLORS = {
|
|
1541
|
-
pdf: "text-red-600",
|
|
1542
|
-
dxf: "text-blue-600",
|
|
1543
|
-
"3d": "text-purple-600",
|
|
1544
|
-
image: "text-emerald-600",
|
|
1545
|
-
csv: "text-green-600"
|
|
1546
|
-
};
|
|
1547
1491
|
var DOCUMENTS_FOLDER_ID = "documents";
|
|
1548
1492
|
var DOCUMENTS_FOLDER_NAME = "Documents";
|
|
1549
|
-
function FileIconTile({ entityType, isSelected, entityId, label, fileKind }) {
|
|
1550
|
-
const isPreviewFile = entityType === "preview-file" && fileKind;
|
|
1551
|
-
const previewColor2 = isPreviewFile ? PREVIEW_FILE_COLORS[fileKind] : null;
|
|
1552
|
-
const previewCode = isPreviewFile ? PREVIEW_FILE_CODES[fileKind] : null;
|
|
1553
|
-
if (entityType === "folder") {
|
|
1554
|
-
return /* @__PURE__ */ jsx("div", { className: `w-12 h-12 flex items-center justify-center ${isSelected ? "rounded-lg bg-blue-400/30 ring-2 ring-blue-500" : ""}`, children: /* @__PURE__ */ jsxs("svg", { className: "h-12 w-12 drop-shadow-[0_2px_3px_rgba(0,0,0,0.3)]", viewBox: "0 0 48 48", children: [
|
|
1555
|
-
/* @__PURE__ */ jsx("path", { d: "M6 12a4 4 0 014-4h10l4 4h14a4 4 0 014 4v20a4 4 0 01-4 4H10a4 4 0 01-4-4V12z", fill: "white", stroke: "#eab308", strokeWidth: "2", strokeLinejoin: "round" }),
|
|
1556
|
-
/* @__PURE__ */ jsx("path", { d: "M6 18h36", stroke: "#eab308", strokeWidth: "1.5" })
|
|
1557
|
-
] }) });
|
|
1558
|
-
}
|
|
1559
|
-
if (entityType === "page") {
|
|
1560
|
-
const icon = label && navIcons[label] || (entityId ? navIcons[entityId] : void 0);
|
|
1561
|
-
return /* @__PURE__ */ jsx("div", { className: `w-12 h-12 flex items-center justify-center ${isSelected ? "rounded-lg bg-blue-400/30 ring-2 ring-blue-500" : ""}`, children: icon && isValidElement(icon) ? cloneElement(icon, { className: "h-10 w-10 text-white drop-shadow-[0_2px_3px_rgba(0,0,0,0.4)]" }) : /* @__PURE__ */ jsx("svg", { className: "h-10 w-10 text-white drop-shadow-[0_2px_3px_rgba(0,0,0,0.4)]", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3.75 6A2.25 2.25 0 016 3.75h2.25A2.25 2.25 0 0110.5 6v2.25a2.25 2.25 0 01-2.25 2.25H6a2.25 2.25 0 01-2.25-2.25V6z" }) }) });
|
|
1562
|
-
}
|
|
1563
|
-
return /* @__PURE__ */ jsxs("div", { className: `w-12 h-12 relative flex items-center justify-center ${isSelected ? "rounded-lg bg-blue-400/30 ring-2 ring-blue-500" : ""}`, children: [
|
|
1564
|
-
/* @__PURE__ */ jsxs("svg", { className: `w-10 h-12 drop-shadow-[0_2px_3px_rgba(0,0,0,0.3)] ${previewColor2 ?? ENTITY_ICON_COLORS[entityType] ?? "text-gray-500"}`, viewBox: "0 0 40 48", fill: "none", children: [
|
|
1565
|
-
/* @__PURE__ */ jsx("path", { d: "M4 0h22l10 10v34a4 4 0 01-4 4H4a4 4 0 01-4-4V4a4 4 0 014-4z", fill: "white", fillOpacity: "0.92" }),
|
|
1566
|
-
/* @__PURE__ */ jsx("path", { d: "M26 0l10 10H30a4 4 0 01-4-4V0z", fill: "currentColor", fillOpacity: "0.2" }),
|
|
1567
|
-
/* @__PURE__ */ jsx("path", { d: "M4 0h22l10 10v34a4 4 0 01-4 4H4a4 4 0 01-4-4V4a4 4 0 014-4z", stroke: "currentColor", strokeWidth: "1.5", strokeOpacity: "0.5" })
|
|
1568
|
-
] }),
|
|
1569
|
-
/* @__PURE__ */ jsx("span", { className: `absolute inset-0 flex items-center justify-center text-[9px] font-bold pt-2 ${previewColor2 ?? ENTITY_ICON_COLORS[entityType] ?? "text-gray-600"}`, children: previewCode ?? ENTITY_ICONS[entityType] ?? entityType.slice(0, 3).toUpperCase() })
|
|
1570
|
-
] });
|
|
1571
|
-
}
|
|
1572
1493
|
var GRID = 90;
|
|
1573
1494
|
function snapToGrid(x, y) {
|
|
1574
1495
|
return { x: Math.round(x / GRID) * GRID, y: Math.round(y / GRID) * GRID };
|
|
@@ -1580,242 +1501,6 @@ function DesktopHostProvider({ value, children }) {
|
|
|
1580
1501
|
function useDesktopHost() {
|
|
1581
1502
|
return useContext(DesktopHostContext);
|
|
1582
1503
|
}
|
|
1583
|
-
var FOLDER_GRID = 90;
|
|
1584
|
-
var FOLDER_ITEM_H = 80;
|
|
1585
|
-
var FOLDER_PAD = 12;
|
|
1586
|
-
function FolderWindow({ folder, items, onClose, onOpen, onMoveOut, onSetFolderPosition, onDragOutToDesktop }) {
|
|
1587
|
-
const [selected, setSelected] = useState(/* @__PURE__ */ new Set());
|
|
1588
|
-
const [rubber, setRubber] = useState(null);
|
|
1589
|
-
const didDragRubber = useRef(false);
|
|
1590
|
-
const bodyRef = useRef(null);
|
|
1591
|
-
const [bodyWidth, setBodyWidth] = useState(800);
|
|
1592
|
-
const setDragOutsideClass = (on) => {
|
|
1593
|
-
const el = bodyRef.current;
|
|
1594
|
-
if (!el) return;
|
|
1595
|
-
el.style.outline = on ? "2px dashed rgb(96 165 250 / 0.6)" : "";
|
|
1596
|
-
el.style.outlineOffset = on ? "-2px" : "";
|
|
1597
|
-
};
|
|
1598
|
-
useEffect(() => {
|
|
1599
|
-
const el = bodyRef.current;
|
|
1600
|
-
if (!el) return;
|
|
1601
|
-
const update = () => setBodyWidth(el.clientWidth);
|
|
1602
|
-
update();
|
|
1603
|
-
const ro = new ResizeObserver(update);
|
|
1604
|
-
ro.observe(el);
|
|
1605
|
-
return () => ro.disconnect();
|
|
1606
|
-
}, []);
|
|
1607
|
-
const cols = Math.max(1, Math.floor((bodyWidth - FOLDER_PAD) / FOLDER_GRID));
|
|
1608
|
-
const getItemFolderPos = (item, idx) => {
|
|
1609
|
-
if (item.folderX != null && item.folderY != null) return { x: item.folderX, y: item.folderY };
|
|
1610
|
-
return { x: FOLDER_PAD + idx % cols * FOLDER_GRID, y: FOLDER_PAD + Math.floor(idx / cols) * FOLDER_GRID };
|
|
1611
|
-
};
|
|
1612
|
-
const toggleSelect = (i, e) => {
|
|
1613
|
-
e.stopPropagation();
|
|
1614
|
-
if (e.shiftKey || e.metaKey || e.ctrlKey) {
|
|
1615
|
-
setSelected((prev) => {
|
|
1616
|
-
const next = new Set(prev);
|
|
1617
|
-
next.has(i) ? next.delete(i) : next.add(i);
|
|
1618
|
-
return next;
|
|
1619
|
-
});
|
|
1620
|
-
} else if (!selected.has(i)) {
|
|
1621
|
-
setSelected(/* @__PURE__ */ new Set([i]));
|
|
1622
|
-
}
|
|
1623
|
-
};
|
|
1624
|
-
const startRubber = (e) => {
|
|
1625
|
-
if (e.button !== 0 || e.target !== bodyRef.current) return;
|
|
1626
|
-
const el = bodyRef.current;
|
|
1627
|
-
const r = el.getBoundingClientRect();
|
|
1628
|
-
const x = e.clientX - r.left + el.scrollLeft;
|
|
1629
|
-
const y = e.clientY - r.top + el.scrollTop;
|
|
1630
|
-
setRubber({ x1: x, y1: y, x2: x, y2: y });
|
|
1631
|
-
didDragRubber.current = false;
|
|
1632
|
-
setSelected(/* @__PURE__ */ new Set());
|
|
1633
|
-
};
|
|
1634
|
-
useEffect(() => {
|
|
1635
|
-
if (!rubber) return;
|
|
1636
|
-
const computeSelection = (minX, maxX, minY, maxY) => {
|
|
1637
|
-
const next = /* @__PURE__ */ new Set();
|
|
1638
|
-
const r = bodyRef.current;
|
|
1639
|
-
if (!r) return next;
|
|
1640
|
-
const tiles = r.querySelectorAll("[data-folder-item]");
|
|
1641
|
-
const containerRect = r.getBoundingClientRect();
|
|
1642
|
-
tiles.forEach((t) => {
|
|
1643
|
-
const tr = t.getBoundingClientRect();
|
|
1644
|
-
const tx = tr.left - containerRect.left + r.scrollLeft;
|
|
1645
|
-
const ty = tr.top - containerRect.top + r.scrollTop;
|
|
1646
|
-
if (tx + tr.width > minX && tx < maxX && ty + tr.height > minY && ty < maxY) {
|
|
1647
|
-
const i = parseInt(t.getAttribute("data-folder-item") || "-1", 10);
|
|
1648
|
-
if (i >= 0) next.add(i);
|
|
1649
|
-
}
|
|
1650
|
-
});
|
|
1651
|
-
return next;
|
|
1652
|
-
};
|
|
1653
|
-
const move = (e) => {
|
|
1654
|
-
const el = bodyRef.current;
|
|
1655
|
-
if (!el) return;
|
|
1656
|
-
const r = el.getBoundingClientRect();
|
|
1657
|
-
const x = e.clientX - r.left + el.scrollLeft;
|
|
1658
|
-
const y = e.clientY - r.top + el.scrollTop;
|
|
1659
|
-
const dx = x - rubber.x1, dy = y - rubber.y1;
|
|
1660
|
-
if (dx * dx + dy * dy > 16) didDragRubber.current = true;
|
|
1661
|
-
setRubber((prev) => prev ? { ...prev, x2: x, y2: y } : null);
|
|
1662
|
-
if (didDragRubber.current) {
|
|
1663
|
-
const minX = Math.min(rubber.x1, x);
|
|
1664
|
-
const maxX = Math.max(rubber.x1, x);
|
|
1665
|
-
const minY = Math.min(rubber.y1, y);
|
|
1666
|
-
const maxY = Math.max(rubber.y1, y);
|
|
1667
|
-
setSelected(computeSelection(minX, maxX, minY, maxY));
|
|
1668
|
-
}
|
|
1669
|
-
};
|
|
1670
|
-
const up = () => setRubber(null);
|
|
1671
|
-
window.addEventListener("pointermove", move);
|
|
1672
|
-
window.addEventListener("pointerup", up);
|
|
1673
|
-
return () => {
|
|
1674
|
-
window.removeEventListener("pointermove", move);
|
|
1675
|
-
window.removeEventListener("pointerup", up);
|
|
1676
|
-
};
|
|
1677
|
-
}, [rubber]);
|
|
1678
|
-
const dragEntriesRef = useRef([]);
|
|
1679
|
-
const dragStartRef = useRef(null);
|
|
1680
|
-
const startItemDrag = (i, e) => {
|
|
1681
|
-
if (e.button !== 0) return;
|
|
1682
|
-
e.stopPropagation();
|
|
1683
|
-
e.preventDefault();
|
|
1684
|
-
const useMulti = selected.has(i) && selected.size > 1;
|
|
1685
|
-
const idxs = useMulti ? Array.from(selected) : [i];
|
|
1686
|
-
if (!useMulti) setSelected(/* @__PURE__ */ new Set([i]));
|
|
1687
|
-
const entries = idxs.map((idx) => {
|
|
1688
|
-
const item = items[idx];
|
|
1689
|
-
const pos = getItemFolderPos(item, idx);
|
|
1690
|
-
const el = bodyRef.current?.querySelector(`[data-folder-item="${idx}"]`) ?? null;
|
|
1691
|
-
return { idx, item, origX: pos.x, origY: pos.y, el };
|
|
1692
|
-
}).filter((e2) => e2.item);
|
|
1693
|
-
dragEntriesRef.current = entries;
|
|
1694
|
-
dragStartRef.current = { clientX: e.clientX, clientY: e.clientY };
|
|
1695
|
-
setDragOutsideClass(false);
|
|
1696
|
-
let moved = false;
|
|
1697
|
-
const move = (ev) => {
|
|
1698
|
-
const start = dragStartRef.current;
|
|
1699
|
-
if (!start) return;
|
|
1700
|
-
const dx = ev.clientX - start.clientX;
|
|
1701
|
-
const dy = ev.clientY - start.clientY;
|
|
1702
|
-
if (!moved && (Math.abs(dx) > 3 || Math.abs(dy) > 3)) moved = true;
|
|
1703
|
-
if (!moved) return;
|
|
1704
|
-
for (const entry of dragEntriesRef.current) {
|
|
1705
|
-
if (!entry.el) continue;
|
|
1706
|
-
entry.el.style.left = `${entry.origX + dx}px`;
|
|
1707
|
-
entry.el.style.top = `${entry.origY + dy}px`;
|
|
1708
|
-
entry.el.style.zIndex = "100";
|
|
1709
|
-
entry.el.style.opacity = "0.85";
|
|
1710
|
-
}
|
|
1711
|
-
const r = bodyRef.current?.getBoundingClientRect();
|
|
1712
|
-
const inside = !!r && ev.clientX >= r.left && ev.clientX <= r.right && ev.clientY >= r.top && ev.clientY <= r.bottom;
|
|
1713
|
-
setDragOutsideClass(!inside);
|
|
1714
|
-
};
|
|
1715
|
-
const up = (ev) => {
|
|
1716
|
-
window.removeEventListener("pointermove", move);
|
|
1717
|
-
window.removeEventListener("pointerup", up);
|
|
1718
|
-
const entries2 = dragEntriesRef.current;
|
|
1719
|
-
dragEntriesRef.current = [];
|
|
1720
|
-
dragStartRef.current = null;
|
|
1721
|
-
for (const entry of entries2) {
|
|
1722
|
-
if (!entry.el) continue;
|
|
1723
|
-
entry.el.style.zIndex = "";
|
|
1724
|
-
entry.el.style.opacity = "";
|
|
1725
|
-
}
|
|
1726
|
-
setDragOutsideClass(false);
|
|
1727
|
-
if (!moved) return;
|
|
1728
|
-
const r = bodyRef.current?.getBoundingClientRect();
|
|
1729
|
-
const inside = !!r && ev.clientX >= r.left && ev.clientX <= r.right && ev.clientY >= r.top && ev.clientY <= r.bottom;
|
|
1730
|
-
if (!inside) {
|
|
1731
|
-
const drops = entries2.map((e2) => ({ item: e2.item, clientX: ev.clientX, clientY: ev.clientY }));
|
|
1732
|
-
setSelected(/* @__PURE__ */ new Set());
|
|
1733
|
-
onDragOutToDesktop(drops);
|
|
1734
|
-
} else {
|
|
1735
|
-
const updates = entries2.map((e2) => {
|
|
1736
|
-
const leftStr = e2.el?.style.left || `${e2.origX}px`;
|
|
1737
|
-
const topStr = e2.el?.style.top || `${e2.origY}px`;
|
|
1738
|
-
const x = Math.max(0, parseFloat(leftStr));
|
|
1739
|
-
const y = Math.max(0, parseFloat(topStr));
|
|
1740
|
-
return { item: e2.item, x, y };
|
|
1741
|
-
});
|
|
1742
|
-
onSetFolderPosition(updates);
|
|
1743
|
-
}
|
|
1744
|
-
};
|
|
1745
|
-
window.addEventListener("pointermove", move);
|
|
1746
|
-
window.addEventListener("pointerup", up);
|
|
1747
|
-
};
|
|
1748
|
-
const moveSelectedOut = () => {
|
|
1749
|
-
if (selected.size === 0) return;
|
|
1750
|
-
onMoveOut(Array.from(selected).map((i) => items[i]).filter(Boolean));
|
|
1751
|
-
setSelected(/* @__PURE__ */ new Set());
|
|
1752
|
-
};
|
|
1753
|
-
const folderIcon = /* @__PURE__ */ jsx("svg", { className: "h-5 w-5 text-amber-500", fill: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx("path", { d: "M2 6a2 2 0 012-2h5l2 2h9a2 2 0 012 2v10a2 2 0 01-2 2H4a2 2 0 01-2-2V6z" }) });
|
|
1754
|
-
const contentHeight = items.reduce((max, item, i) => {
|
|
1755
|
-
const pos = getItemFolderPos(item, i);
|
|
1756
|
-
return Math.max(max, pos.y + FOLDER_ITEM_H + FOLDER_PAD);
|
|
1757
|
-
}, 300);
|
|
1758
|
-
return /* @__PURE__ */ jsx(Modal, { open: true, onClose, title: folder.name, icon: folderIcon, size: "lg", children: /* @__PURE__ */ jsxs(
|
|
1759
|
-
"div",
|
|
1760
|
-
{
|
|
1761
|
-
ref: bodyRef,
|
|
1762
|
-
onPointerDown: startRubber,
|
|
1763
|
-
onClick: () => {
|
|
1764
|
-
if (didDragRubber.current) {
|
|
1765
|
-
didDragRubber.current = false;
|
|
1766
|
-
return;
|
|
1767
|
-
}
|
|
1768
|
-
setSelected(/* @__PURE__ */ new Set());
|
|
1769
|
-
},
|
|
1770
|
-
className: "relative h-full min-h-[300px] p-3 overflow-auto",
|
|
1771
|
-
style: {
|
|
1772
|
-
background: "linear-gradient(135deg, rgba(254, 243, 199, 0.55) 0%, rgba(253, 230, 138, 0.4) 50%, rgba(252, 211, 77, 0.3) 100%)"
|
|
1773
|
-
},
|
|
1774
|
-
children: [
|
|
1775
|
-
selected.size > 0 && /* @__PURE__ */ jsxs("div", { className: "sticky top-0 z-20 mb-2 flex items-center gap-2 px-2 py-1 rounded-md bg-white/80 backdrop-blur-sm shadow border border-gray-200 text-xs text-gray-700 w-fit", children: [
|
|
1776
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
1777
|
-
selected.size,
|
|
1778
|
-
" selected"
|
|
1779
|
-
] }),
|
|
1780
|
-
/* @__PURE__ */ jsx("button", { onClick: moveSelectedOut, className: "px-2 py-0.5 rounded text-blue-600 hover:bg-blue-50", children: "Move to desktop" }),
|
|
1781
|
-
/* @__PURE__ */ jsx("button", { onClick: () => setSelected(/* @__PURE__ */ new Set()), className: "px-2 py-0.5 rounded text-gray-500 hover:bg-gray-100", children: "Clear" })
|
|
1782
|
-
] }),
|
|
1783
|
-
items.length === 0 ? /* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500 text-center py-8 italic", children: "Folder is empty. Drag documents here." }) : /* @__PURE__ */ jsx("div", { className: "relative", style: { height: contentHeight }, children: items.map((item, i) => {
|
|
1784
|
-
const isSelected = selected.has(i);
|
|
1785
|
-
const pos = getItemFolderPos(item, i);
|
|
1786
|
-
return /* @__PURE__ */ jsx(
|
|
1787
|
-
"div",
|
|
1788
|
-
{
|
|
1789
|
-
"data-folder-item": i,
|
|
1790
|
-
onPointerDown: (e) => startItemDrag(i, e),
|
|
1791
|
-
onClick: (e) => toggleSelect(i, e),
|
|
1792
|
-
onDoubleClick: () => onOpen(item),
|
|
1793
|
-
style: { position: "absolute", left: pos.x, top: pos.y },
|
|
1794
|
-
className: "cursor-default select-none",
|
|
1795
|
-
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1 w-20 p-2", children: [
|
|
1796
|
-
/* @__PURE__ */ jsx(FileIconTile, { entityType: item.entityType, isSelected, entityId: item.entityId, label: item.label, fileKind: item.fileKind }),
|
|
1797
|
-
/* @__PURE__ */ jsx("span", { className: `text-[10px] font-medium text-center leading-tight truncate w-full ${isSelected ? "text-blue-900 bg-blue-200/60 rounded px-1" : "text-gray-700"}`, children: item.label })
|
|
1798
|
-
] })
|
|
1799
|
-
},
|
|
1800
|
-
`${item.entityType}-${item.entityId}-${i}`
|
|
1801
|
-
);
|
|
1802
|
-
}) }),
|
|
1803
|
-
rubber && /* @__PURE__ */ jsx(
|
|
1804
|
-
"div",
|
|
1805
|
-
{
|
|
1806
|
-
className: "absolute border border-blue-500 bg-blue-500/10 pointer-events-none",
|
|
1807
|
-
style: {
|
|
1808
|
-
left: Math.min(rubber.x1, rubber.x2),
|
|
1809
|
-
top: Math.min(rubber.y1, rubber.y2),
|
|
1810
|
-
width: Math.abs(rubber.x2 - rubber.x1),
|
|
1811
|
-
height: Math.abs(rubber.y2 - rubber.y1)
|
|
1812
|
-
}
|
|
1813
|
-
}
|
|
1814
|
-
)
|
|
1815
|
-
]
|
|
1816
|
-
}
|
|
1817
|
-
) });
|
|
1818
|
-
}
|
|
1819
1504
|
function Desktop({ profile }) {
|
|
1820
1505
|
useQueryClient();
|
|
1821
1506
|
const { openEntity, openPage } = useWindowManager();
|
|
@@ -1918,7 +1603,6 @@ function Desktop({ profile }) {
|
|
|
1918
1603
|
const [contextMenu, setContextMenu] = useState(null);
|
|
1919
1604
|
const [selected, setSelected] = useState(/* @__PURE__ */ new Set());
|
|
1920
1605
|
const [rubberBand, setRubberBand] = useState(null);
|
|
1921
|
-
const [openFolder, setOpenFolder] = useState(null);
|
|
1922
1606
|
const [aboutOpen, setAboutOpen] = useState(false);
|
|
1923
1607
|
const [whatsNewOpen, setWhatsNewOpen] = useState(false);
|
|
1924
1608
|
const [widgetsOpen, setWidgetsOpen] = useState(false);
|
|
@@ -1941,13 +1625,13 @@ function Desktop({ profile }) {
|
|
|
1941
1625
|
if (host.saveSnap) host.saveSnap(v);
|
|
1942
1626
|
else saveShellPrefs({ desktop_snap: v });
|
|
1943
1627
|
}, [host, saveShellPrefs]);
|
|
1944
|
-
const
|
|
1945
|
-
|
|
1628
|
+
const liveStateRef = useRef({ folders, favDocs, saveFolders, saveDocs });
|
|
1629
|
+
liveStateRef.current = { folders, favDocs, saveFolders, saveDocs };
|
|
1946
1630
|
useEffect(() => {
|
|
1947
1631
|
const handler = (e) => {
|
|
1948
1632
|
const detail = e.detail;
|
|
1949
1633
|
if (!detail?.filePath) return;
|
|
1950
|
-
const { folders: fs, favDocs: docs, saveFolders: sf, saveDocs: sd } =
|
|
1634
|
+
const { folders: fs, favDocs: docs, saveFolders: sf, saveDocs: sd } = liveStateRef.current;
|
|
1951
1635
|
if (!fs.some((f) => f.id === DOCUMENTS_FOLDER_ID)) {
|
|
1952
1636
|
sf([...fs, { id: DOCUMENTS_FOLDER_ID, name: DOCUMENTS_FOLDER_NAME }]);
|
|
1953
1637
|
}
|
|
@@ -1982,6 +1666,36 @@ function Desktop({ profile }) {
|
|
|
1982
1666
|
};
|
|
1983
1667
|
const desktopItems = favDocs.filter((d) => !d.folderId);
|
|
1984
1668
|
const folderItems = (folderId) => favDocs.filter((d) => d.folderId === folderId);
|
|
1669
|
+
const openItem = (item) => {
|
|
1670
|
+
if (item.entityType === "preview-file" && item.filePath && item.fileKind) {
|
|
1671
|
+
openPreviewFile({
|
|
1672
|
+
filePath: item.filePath,
|
|
1673
|
+
filename: item.label,
|
|
1674
|
+
kind: item.fileKind,
|
|
1675
|
+
onStaged: (route) => openPage(route)
|
|
1676
|
+
});
|
|
1677
|
+
} else if (item.entityType === "page") {
|
|
1678
|
+
openPage(item.entityId);
|
|
1679
|
+
} else {
|
|
1680
|
+
openEntity(item.entityType, item.entityId, null, item.label);
|
|
1681
|
+
}
|
|
1682
|
+
};
|
|
1683
|
+
const openDesktopFolder = (folderId) => {
|
|
1684
|
+
requestFilesDesktopFolderView(folderId);
|
|
1685
|
+
openPage("/files");
|
|
1686
|
+
};
|
|
1687
|
+
const bridgeMoveToDesktop = useCallback((toMove) => {
|
|
1688
|
+
const { favDocs: docs, saveDocs: sd } = liveStateRef.current;
|
|
1689
|
+
const ids = new Set(toMove.map((t) => `${t.entityType}|${t.entityId}`));
|
|
1690
|
+
sd(docs.map(
|
|
1691
|
+
(d) => d.folderId && ids.has(`${d.entityType}|${d.entityId}`) ? { ...d, folderId: void 0, folderX: void 0, folderY: void 0 } : d
|
|
1692
|
+
));
|
|
1693
|
+
}, []);
|
|
1694
|
+
const bridgeRemoveShortcuts = useCallback((toRemove) => {
|
|
1695
|
+
const { favDocs: docs, saveDocs: sd } = liveStateRef.current;
|
|
1696
|
+
const ids = new Set(toRemove.map((t) => `${t.entityType}|${t.entityId}`));
|
|
1697
|
+
sd(docs.filter((d) => !(d.folderId && ids.has(`${d.entityType}|${d.entityId}`))));
|
|
1698
|
+
}, []);
|
|
1985
1699
|
const [localPositions, setLocalPositions] = useState({});
|
|
1986
1700
|
const dragEntriesRef = useRef([]);
|
|
1987
1701
|
const startDrag = (type, idx, e) => {
|
|
@@ -2138,6 +1852,21 @@ function Desktop({ profile }) {
|
|
|
2138
1852
|
useEffect(() => {
|
|
2139
1853
|
setLocalPositions({});
|
|
2140
1854
|
}, [favDocsKey, foldersKey]);
|
|
1855
|
+
useEffect(() => {
|
|
1856
|
+
const { folders: fs, favDocs: docs } = liveStateRef.current;
|
|
1857
|
+
const itemsByFolder = {};
|
|
1858
|
+
for (const f of fs) itemsByFolder[f.id] = [];
|
|
1859
|
+
for (const d of docs) {
|
|
1860
|
+
if (d.folderId && itemsByFolder[d.folderId]) itemsByFolder[d.folderId].push(d);
|
|
1861
|
+
}
|
|
1862
|
+
publishDesktopFolders({
|
|
1863
|
+
folders: fs.map((f) => ({ id: f.id, name: f.name, itemCount: itemsByFolder[f.id]?.length ?? 0 })),
|
|
1864
|
+
itemsByFolder,
|
|
1865
|
+
moveToDesktop: bridgeMoveToDesktop,
|
|
1866
|
+
removeShortcuts: bridgeRemoveShortcuts
|
|
1867
|
+
});
|
|
1868
|
+
}, [favDocsKey, foldersKey, bridgeMoveToDesktop, bridgeRemoveShortcuts]);
|
|
1869
|
+
useEffect(() => () => publishDesktopFolders(null), []);
|
|
2141
1870
|
const didRubberBandDragRef = useRef(false);
|
|
2142
1871
|
const startRubberBand = (e) => {
|
|
2143
1872
|
if (e.button !== 0 || e.target !== containerRef.current) return;
|
|
@@ -2167,6 +1896,16 @@ function Desktop({ profile }) {
|
|
|
2167
1896
|
sel.add(`folder-${i}`);
|
|
2168
1897
|
}
|
|
2169
1898
|
});
|
|
1899
|
+
const trashEl = containerRef.current?.querySelector('[data-desktop-icon="trash"]');
|
|
1900
|
+
const containerRect = containerRef.current?.getBoundingClientRect();
|
|
1901
|
+
if (trashEl && containerRect) {
|
|
1902
|
+
const tr = trashEl.getBoundingClientRect();
|
|
1903
|
+
const tx = tr.left - containerRect.left;
|
|
1904
|
+
const ty = tr.top - containerRect.top;
|
|
1905
|
+
if (tx + tr.width > minX && tx < maxX && ty + tr.height > minY && ty < maxY) {
|
|
1906
|
+
sel.add("trash");
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
2170
1909
|
return sel;
|
|
2171
1910
|
};
|
|
2172
1911
|
const move = (e) => {
|
|
@@ -2407,6 +2146,7 @@ function Desktop({ profile }) {
|
|
|
2407
2146
|
const trashPos = prefs.desktop_trash_position;
|
|
2408
2147
|
const right = trashPos?.right ?? defaultRight;
|
|
2409
2148
|
const bottom = trashPos?.bottom ?? defaultBottom;
|
|
2149
|
+
const isTrashSelected = selected.has("trash");
|
|
2410
2150
|
const startTrashDrag = (e) => {
|
|
2411
2151
|
if (e.button !== 0) return;
|
|
2412
2152
|
e.preventDefault();
|
|
@@ -2443,18 +2183,28 @@ function Desktop({ profile }) {
|
|
|
2443
2183
|
"data-desktop-icon": "trash",
|
|
2444
2184
|
style: { position: "absolute", right, bottom, zIndex: 1 },
|
|
2445
2185
|
onPointerDown: startTrashDrag,
|
|
2446
|
-
onClick: (e) =>
|
|
2186
|
+
onClick: (e) => {
|
|
2187
|
+
e.stopPropagation();
|
|
2188
|
+
if (e.shiftKey || e.metaKey || e.ctrlKey) {
|
|
2189
|
+
setSelected((prev) => {
|
|
2190
|
+
const next = new Set(prev);
|
|
2191
|
+
next.has("trash") ? next.delete("trash") : next.add("trash");
|
|
2192
|
+
return next;
|
|
2193
|
+
});
|
|
2194
|
+
} else if (!selected.has("trash")) {
|
|
2195
|
+
setSelected(/* @__PURE__ */ new Set(["trash"]));
|
|
2196
|
+
}
|
|
2197
|
+
},
|
|
2447
2198
|
onContextMenu: (e) => e.preventDefault(),
|
|
2448
2199
|
onDoubleClick: (e) => {
|
|
2449
2200
|
e.stopPropagation();
|
|
2450
|
-
|
|
2451
|
-
window.dispatchEvent(new CustomEvent("react-os-shell:files-show-trash"));
|
|
2201
|
+
requestFilesTrashView();
|
|
2452
2202
|
openPage("/files");
|
|
2453
2203
|
},
|
|
2454
2204
|
className: "cursor-default select-none",
|
|
2455
2205
|
title: "Trash \u2014 double-click to open, drag to move",
|
|
2456
2206
|
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1 w-20 p-2", children: [
|
|
2457
|
-
/* @__PURE__ */ jsx("div", { className:
|
|
2207
|
+
/* @__PURE__ */ jsx("div", { className: `w-12 h-12 flex items-center justify-center ${isTrashSelected ? "rounded-lg bg-blue-400/30 ring-2 ring-blue-500" : ""}`, children: /* @__PURE__ */ jsx("svg", { className: "h-12 w-12 drop-shadow-[0_2px_3px_rgba(0,0,0,0.4)]", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx(
|
|
2458
2208
|
"path",
|
|
2459
2209
|
{
|
|
2460
2210
|
fill: "#c0c4cc",
|
|
@@ -2466,7 +2216,7 @@ function Desktop({ profile }) {
|
|
|
2466
2216
|
d: "M16.5 4.478v.227a48.816 48.816 0 013.878.512.75.75 0 11-.256 1.478l-.209-.035-1.005 13.07a3 3 0 01-2.991 2.77H8.084a3 3 0 01-2.991-2.77L4.087 6.66l-.209.035a.75.75 0 01-.256-1.478A48.567 48.567 0 017.5 4.705v-.227c0-1.564 1.213-2.9 2.816-2.951a52.662 52.662 0 014.368 0c1.603.051 2.816 1.387 2.816 2.951zm-6.136-1.452a51.196 51.196 0 013.273 0C14.39 3.05 15 3.684 15 4.478v.113a49.488 49.488 0 00-6 0v-.113c0-.794.609-1.428 1.364-1.452zm-.355 5.945a.75.75 0 10-1.5.058l.347 9a.75.75 0 101.499-.058l-.346-9zm5.48.058a.75.75 0 10-1.498-.058l-.347 9a.75.75 0 001.5.058l.346-9z"
|
|
2467
2217
|
}
|
|
2468
2218
|
) }) }),
|
|
2469
|
-
/* @__PURE__ */ jsx("span", { className:
|
|
2219
|
+
/* @__PURE__ */ jsx("span", { className: `text-[10px] font-medium text-center leading-tight drop-shadow-[0_1px_2px_rgba(0,0,0,0.8)] ${isTrashSelected ? "text-blue-200 bg-blue-600/60 rounded px-1" : "text-white"}`, children: "Trash" })
|
|
2470
2220
|
] })
|
|
2471
2221
|
}
|
|
2472
2222
|
);
|
|
@@ -2499,18 +2249,7 @@ function Desktop({ profile }) {
|
|
|
2499
2249
|
onContextMenu: (e) => handleItemContextMenu(e, i),
|
|
2500
2250
|
onDoubleClick: (e) => {
|
|
2501
2251
|
e.stopPropagation();
|
|
2502
|
-
|
|
2503
|
-
openPreviewFile({
|
|
2504
|
-
filePath: doc.filePath,
|
|
2505
|
-
filename: doc.label,
|
|
2506
|
-
kind: doc.fileKind,
|
|
2507
|
-
onStaged: (route) => openPage(route)
|
|
2508
|
-
});
|
|
2509
|
-
} else if (doc.entityType === "page") {
|
|
2510
|
-
openPage(doc.entityId);
|
|
2511
|
-
} else {
|
|
2512
|
-
openEntity(doc.entityType, doc.entityId, null, doc.label);
|
|
2513
|
-
}
|
|
2252
|
+
openItem(doc);
|
|
2514
2253
|
},
|
|
2515
2254
|
className: "cursor-default select-none",
|
|
2516
2255
|
children: renderIcon(doc.entityType, doc.label, isSelected, doc.entityId, doc.fileKind)
|
|
@@ -2554,14 +2293,11 @@ function Desktop({ profile }) {
|
|
|
2554
2293
|
onContextMenu: (e) => handleFolderContextMenu(e, i),
|
|
2555
2294
|
onDoubleClick: (e) => {
|
|
2556
2295
|
e.stopPropagation();
|
|
2557
|
-
|
|
2296
|
+
openDesktopFolder(folder.id);
|
|
2558
2297
|
},
|
|
2559
2298
|
className: "cursor-default select-none",
|
|
2560
2299
|
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1 w-20 p-2", children: [
|
|
2561
|
-
/* @__PURE__ */ jsx("div", { className: `w-12 h-12 flex items-center justify-center ${isSelected ? "rounded-lg bg-blue-400/30 ring-2 ring-blue-500" : ""} ${isHovered ? "rounded-lg ring-4 ring-amber-400 shadow-[0_0_20px_rgba(245,158,11,0.6)]" : ""}`, children: /* @__PURE__ */
|
|
2562
|
-
/* @__PURE__ */ jsx("path", { d: "M6 12a4 4 0 014-4h10l4 4h14a4 4 0 014 4v20a4 4 0 01-4 4H10a4 4 0 01-4-4V12z", fill: "white", stroke: "#eab308", strokeWidth: "2", strokeLinejoin: "round" }),
|
|
2563
|
-
/* @__PURE__ */ jsx("path", { d: "M6 18h36", stroke: "#eab308", strokeWidth: "1.5" })
|
|
2564
|
-
] }) }),
|
|
2300
|
+
/* @__PURE__ */ jsx("div", { className: `w-12 h-12 flex items-center justify-center ${isSelected ? "rounded-lg bg-blue-400/30 ring-2 ring-blue-500" : ""} ${isHovered ? "rounded-lg ring-4 ring-amber-400 shadow-[0_0_20px_rgba(245,158,11,0.6)]" : ""}`, children: /* @__PURE__ */ jsx(FolderGlyph, { className: "h-12 w-12 text-amber-500 drop-shadow-[0_2px_3px_rgba(0,0,0,0.3)]" }) }),
|
|
2565
2301
|
renamingFolder === folder.id ? /* @__PURE__ */ jsx(
|
|
2566
2302
|
"input",
|
|
2567
2303
|
{
|
|
@@ -2788,8 +2524,7 @@ function Desktop({ profile }) {
|
|
|
2788
2524
|
] }),
|
|
2789
2525
|
contextMenu && contextMenu.itemIdx != null && /* @__PURE__ */ jsxs(PopupMenu, { style: menuStyle(contextMenu.x, contextMenu.y), minWidth: 160, children: [
|
|
2790
2526
|
/* @__PURE__ */ jsx(PopupMenuItem, { onClick: () => {
|
|
2791
|
-
|
|
2792
|
-
d.entityType === "page" ? openPage(d.entityId) : openEntity(d.entityType, d.entityId, null, d.label);
|
|
2527
|
+
openItem(desktopItems[contextMenu.itemIdx]);
|
|
2793
2528
|
setContextMenu(null);
|
|
2794
2529
|
}, children: "Open" }),
|
|
2795
2530
|
/* @__PURE__ */ jsx(PopupMenuDivider, {}),
|
|
@@ -2797,7 +2532,7 @@ function Desktop({ profile }) {
|
|
|
2797
2532
|
] }),
|
|
2798
2533
|
contextMenu && contextMenu.folderIdx != null && /* @__PURE__ */ jsxs(PopupMenu, { style: menuStyle(contextMenu.x, contextMenu.y), minWidth: 160, children: [
|
|
2799
2534
|
/* @__PURE__ */ jsx(PopupMenuItem, { onClick: () => {
|
|
2800
|
-
|
|
2535
|
+
openDesktopFolder(folders[contextMenu.folderIdx].id);
|
|
2801
2536
|
setContextMenu(null);
|
|
2802
2537
|
}, children: "Open" }),
|
|
2803
2538
|
/* @__PURE__ */ jsx(PopupMenuItem, { onClick: () => {
|
|
@@ -2808,68 +2543,6 @@ function Desktop({ profile }) {
|
|
|
2808
2543
|
/* @__PURE__ */ jsx(PopupMenuDivider, {}),
|
|
2809
2544
|
/* @__PURE__ */ jsx(PopupMenuItem, { danger: true, onClick: () => removeFolder(contextMenu.folderIdx), children: "Delete Folder" })
|
|
2810
2545
|
] }),
|
|
2811
|
-
openFolder && (() => {
|
|
2812
|
-
const folder = folders.find((f) => f.id === openFolder);
|
|
2813
|
-
if (!folder) return null;
|
|
2814
|
-
return /* @__PURE__ */ jsx(
|
|
2815
|
-
FolderWindow,
|
|
2816
|
-
{
|
|
2817
|
-
folder,
|
|
2818
|
-
items: folderItems(openFolder),
|
|
2819
|
-
onClose: () => setOpenFolder(null),
|
|
2820
|
-
onOpen: (item) => {
|
|
2821
|
-
if (item.entityType === "preview-file" && item.filePath && item.fileKind) {
|
|
2822
|
-
openPreviewFile({
|
|
2823
|
-
filePath: item.filePath,
|
|
2824
|
-
filename: item.label,
|
|
2825
|
-
kind: item.fileKind,
|
|
2826
|
-
onStaged: (route) => openPage(route)
|
|
2827
|
-
});
|
|
2828
|
-
} else {
|
|
2829
|
-
openEntity(item.entityType, item.entityId, null, item.label);
|
|
2830
|
-
}
|
|
2831
|
-
},
|
|
2832
|
-
onMoveOut: (toMove) => {
|
|
2833
|
-
const ids = new Set(toMove.map((t) => `${t.entityType}|${t.entityId}`));
|
|
2834
|
-
const updated = favDocs.map(
|
|
2835
|
-
(d) => d.folderId === openFolder && ids.has(`${d.entityType}|${d.entityId}`) ? { ...d, folderId: void 0, folderX: void 0, folderY: void 0 } : d
|
|
2836
|
-
);
|
|
2837
|
-
saveDocs(updated);
|
|
2838
|
-
},
|
|
2839
|
-
onSetFolderPosition: (updates) => {
|
|
2840
|
-
const patch = new Map(updates.map((u) => [`${u.item.entityType}|${u.item.entityId}`, u]));
|
|
2841
|
-
const updated = favDocs.map((d) => {
|
|
2842
|
-
const u = patch.get(`${d.entityType}|${d.entityId}`);
|
|
2843
|
-
return u ? { ...d, folderX: u.x, folderY: u.y } : d;
|
|
2844
|
-
});
|
|
2845
|
-
saveDocs(updated);
|
|
2846
|
-
},
|
|
2847
|
-
onDragOutToDesktop: (drops) => {
|
|
2848
|
-
const containerRect = containerRef.current?.getBoundingClientRect();
|
|
2849
|
-
const cw = containerRef.current?.clientWidth ?? window.innerWidth;
|
|
2850
|
-
const patch = /* @__PURE__ */ new Map();
|
|
2851
|
-
for (const d of drops) {
|
|
2852
|
-
const offX = containerRect ? d.clientX - containerRect.left : d.clientX;
|
|
2853
|
-
const offY = containerRect ? d.clientY - containerRect.top : d.clientY;
|
|
2854
|
-
let right = cw - offX - 40;
|
|
2855
|
-
let top = Math.max(0, offY - 40);
|
|
2856
|
-
if (snapEnabled) {
|
|
2857
|
-
const s = snapToGrid(right, top);
|
|
2858
|
-
right = s.x;
|
|
2859
|
-
top = s.y;
|
|
2860
|
-
}
|
|
2861
|
-
right = Math.max(0, right);
|
|
2862
|
-
patch.set(`${d.item.entityType}|${d.item.entityId}`, { right, top });
|
|
2863
|
-
}
|
|
2864
|
-
const updated = favDocs.map((d) => {
|
|
2865
|
-
const p = patch.get(`${d.entityType}|${d.entityId}`);
|
|
2866
|
-
return p ? { ...d, folderId: void 0, folderX: void 0, folderY: void 0, x: p.right, y: p.top } : d;
|
|
2867
|
-
});
|
|
2868
|
-
saveDocs(updated);
|
|
2869
|
-
}
|
|
2870
|
-
}
|
|
2871
|
-
);
|
|
2872
|
-
})(),
|
|
2873
2546
|
/* @__PURE__ */ jsx(WidgetManager, { open: widgetsOpen, onClose: () => setWidgetsOpen(false) }),
|
|
2874
2547
|
aboutOpen && (() => {
|
|
2875
2548
|
const version = host.productVersion ?? APP_VERSION;
|
|
@@ -3704,28 +3377,6 @@ function subscribeMobileMode(cb) {
|
|
|
3704
3377
|
var MOBILE_WIDGET_ORDER_KEY = "erp_mobile_widget_order";
|
|
3705
3378
|
var MOBILE_HOME_ORDER_KEY = "erp_mobile_home_order";
|
|
3706
3379
|
var LONG_PRESS_MS = 400;
|
|
3707
|
-
var ICON_GRADIENTS = [
|
|
3708
|
-
"from-blue-500 to-blue-700",
|
|
3709
|
-
"from-indigo-500 to-purple-600",
|
|
3710
|
-
"from-purple-500 to-pink-600",
|
|
3711
|
-
"from-pink-500 to-rose-600",
|
|
3712
|
-
"from-red-500 to-rose-600",
|
|
3713
|
-
"from-orange-500 to-red-600",
|
|
3714
|
-
"from-amber-500 to-orange-600",
|
|
3715
|
-
"from-yellow-500 to-amber-500",
|
|
3716
|
-
"from-lime-500 to-green-600",
|
|
3717
|
-
"from-green-500 to-emerald-600",
|
|
3718
|
-
"from-emerald-500 to-teal-600",
|
|
3719
|
-
"from-teal-500 to-cyan-600",
|
|
3720
|
-
"from-cyan-500 to-sky-600",
|
|
3721
|
-
"from-sky-500 to-blue-600",
|
|
3722
|
-
"from-violet-500 to-fuchsia-600"
|
|
3723
|
-
];
|
|
3724
|
-
function hashGradient(seed) {
|
|
3725
|
-
let h = 0;
|
|
3726
|
-
for (let i = 0; i < seed.length; i++) h = (h << 5) - h + seed.charCodeAt(i);
|
|
3727
|
-
return ICON_GRADIENTS[Math.abs(h) % ICON_GRADIENTS.length];
|
|
3728
|
-
}
|
|
3729
3380
|
function loadOrder(key) {
|
|
3730
3381
|
try {
|
|
3731
3382
|
const raw = localStorage.getItem(key);
|