react-os-shell 0.2.2 → 0.2.20
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-IAQ5N3LL.js → Browser-RJZLTAJQ.js} +3 -3
- package/dist/{Browser-IAQ5N3LL.js.map → Browser-RJZLTAJQ.js.map} +1 -1
- package/dist/{Calculator-7MIONNJK.js → Calculator-DMROKOY2.js} +4 -4
- package/dist/{Calculator-7MIONNJK.js.map → Calculator-DMROKOY2.js.map} +1 -1
- package/dist/{Calendar-2R2DWXTG.js → Calendar-24TAKCAJ.js} +3 -3
- package/dist/{Calendar-2R2DWXTG.js.map → Calendar-24TAKCAJ.js.map} +1 -1
- package/dist/{CurrencyConverter-BMTB7FLA.js → CurrencyConverter-KMBBKLHZ.js} +4 -4
- package/dist/{CurrencyConverter-BMTB7FLA.js.map → CurrencyConverter-KMBBKLHZ.js.map} +1 -1
- package/dist/{Documents-CBNJAM3Q.js → Documents-QMP6QN3C.js} +3 -3
- package/dist/{Documents-CBNJAM3Q.js.map → Documents-QMP6QN3C.js.map} +1 -1
- package/dist/{Email-BS6MESSZ.js → Email-XTFUEIE5.js} +3 -3
- package/dist/{Email-BS6MESSZ.js.map → Email-XTFUEIE5.js.map} +1 -1
- package/dist/Files-GMIYQPAA.js +7 -0
- package/dist/{Files-U3BSTCC3.js.map → Files-GMIYQPAA.js.map} +1 -1
- package/dist/{Minesweeper-XOSH6BW2.js → Minesweeper-YPAR6SPJ.js} +3 -3
- package/dist/{Minesweeper-XOSH6BW2.js.map → Minesweeper-YPAR6SPJ.js.map} +1 -1
- package/dist/{Notepad-DMSBGGMS.js → Notepad-VEEUZROP.js} +3 -3
- package/dist/{Notepad-DMSBGGMS.js.map → Notepad-VEEUZROP.js.map} +1 -1
- package/dist/{PomodoroTimer-3XLLIDV3.js → PomodoroTimer-HWHMQZO6.js} +4 -4
- package/dist/{PomodoroTimer-3XLLIDV3.js.map → PomodoroTimer-HWHMQZO6.js.map} +1 -1
- package/dist/Preview-Z447TOCE.js +6 -0
- package/dist/{Preview-Y2LMO2DL.js.map → Preview-Z447TOCE.js.map} +1 -1
- package/dist/{Spreadsheet-IRPGCABR.js → Spreadsheet-W76QOD42.js} +3 -3
- package/dist/{Spreadsheet-IRPGCABR.js.map → Spreadsheet-W76QOD42.js.map} +1 -1
- package/dist/{Weather-5IW43PAQ.js → Weather-DIKN7BOT.js} +4 -4
- package/dist/{Weather-5IW43PAQ.js.map → Weather-DIKN7BOT.js.map} +1 -1
- package/dist/apps/index.js +16 -16
- package/dist/{chunk-IQV6QQBQ.js → chunk-4J466VCS.js} +3 -3
- package/dist/{chunk-IQV6QQBQ.js.map → chunk-4J466VCS.js.map} +1 -1
- package/dist/{chunk-JEJHECSO.js → chunk-7ZUE7PEH.js} +4 -4
- package/dist/{chunk-JEJHECSO.js.map → chunk-7ZUE7PEH.js.map} +1 -1
- package/dist/{chunk-DIJ46HNS.js → chunk-HVZUPS3P.js} +3 -3
- package/dist/{chunk-DIJ46HNS.js.map → chunk-HVZUPS3P.js.map} +1 -1
- package/dist/{chunk-7P6DO3NC.js → chunk-QXY6ZHRX.js} +73 -35
- package/dist/chunk-QXY6ZHRX.js.map +1 -0
- package/dist/index.d.ts +19 -3
- package/dist/index.js +124 -113
- package/dist/index.js.map +1 -1
- package/dist/styles.css +11 -0
- package/package.json +1 -1
- package/dist/Files-U3BSTCC3.js +0 -7
- package/dist/Preview-Y2LMO2DL.js +0 -6
- package/dist/chunk-7P6DO3NC.js.map +0 -1
|
@@ -69,14 +69,26 @@ var _apiClient = null;
|
|
|
69
69
|
function setShellApiClient(instance) {
|
|
70
70
|
_apiClient = instance;
|
|
71
71
|
}
|
|
72
|
+
function isShellApiClientConfigured() {
|
|
73
|
+
return _apiClient !== null;
|
|
74
|
+
}
|
|
75
|
+
var NOOP_METHODS = /* @__PURE__ */ new Set([
|
|
76
|
+
"get",
|
|
77
|
+
"post",
|
|
78
|
+
"put",
|
|
79
|
+
"patch",
|
|
80
|
+
"delete",
|
|
81
|
+
"head",
|
|
82
|
+
"options",
|
|
83
|
+
"request"
|
|
84
|
+
]);
|
|
72
85
|
var apiClient = new Proxy({}, {
|
|
73
86
|
get(_t, prop) {
|
|
74
|
-
if (
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
);
|
|
87
|
+
if (_apiClient) return _apiClient[prop];
|
|
88
|
+
if (typeof prop === "string" && NOOP_METHODS.has(prop)) {
|
|
89
|
+
return () => Promise.resolve({ data: null, status: 0, statusText: "", headers: {}, config: {} });
|
|
78
90
|
}
|
|
79
|
-
return
|
|
91
|
+
return void 0;
|
|
80
92
|
}
|
|
81
93
|
});
|
|
82
94
|
var client_default = apiClient;
|
|
@@ -117,7 +129,7 @@ function glassStyle(opacity) {
|
|
|
117
129
|
};
|
|
118
130
|
}
|
|
119
131
|
var GLASS_DIVIDER = "border-white/20";
|
|
120
|
-
var GLASS_INPUT_BG = "bg
|
|
132
|
+
var GLASS_INPUT_BG = "glass-input-bg";
|
|
121
133
|
function getDensity() {
|
|
122
134
|
return getComputedStyle(document.documentElement).getPropertyValue("--menu-density")?.trim() || "normal";
|
|
123
135
|
}
|
|
@@ -261,21 +273,21 @@ function useIsMobile() {
|
|
|
261
273
|
return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
262
274
|
}
|
|
263
275
|
|
|
264
|
-
// src/shell/
|
|
265
|
-
var
|
|
266
|
-
var
|
|
267
|
-
function
|
|
268
|
-
return
|
|
276
|
+
// src/shell/mobileSwipeStore.ts
|
|
277
|
+
var _parentKey = null;
|
|
278
|
+
var subs = /* @__PURE__ */ new Set();
|
|
279
|
+
function getSwipingParentKey() {
|
|
280
|
+
return _parentKey;
|
|
269
281
|
}
|
|
270
|
-
function
|
|
271
|
-
if (
|
|
272
|
-
|
|
273
|
-
|
|
282
|
+
function setSwipingParentKey(key) {
|
|
283
|
+
if (_parentKey === key) return;
|
|
284
|
+
_parentKey = key;
|
|
285
|
+
for (const cb of subs) cb();
|
|
274
286
|
}
|
|
275
|
-
function
|
|
276
|
-
|
|
287
|
+
function subscribeSwipingParentKey(cb) {
|
|
288
|
+
subs.add(cb);
|
|
277
289
|
return () => {
|
|
278
|
-
|
|
290
|
+
subs.delete(cb);
|
|
279
291
|
};
|
|
280
292
|
}
|
|
281
293
|
var ModalIdContext = createContext("");
|
|
@@ -547,7 +559,7 @@ function useIsActiveModal(modalId) {
|
|
|
547
559
|
function triggerSplitView() {
|
|
548
560
|
window.dispatchEvent(new CustomEvent("modal-split-view"));
|
|
549
561
|
}
|
|
550
|
-
function Modal({ open, onClose, title, icon, copyText, size = "lg", dirty = false, onNext, onPrev, footer, bodyScroll, onMinimize, initialBox, actions, actionsLeft, allowPinOnTop, initialPosition, widget, compact, appStyle, autoHeight, autoMinHeight, widgetMenu, dimensions, windowKey, children }) {
|
|
562
|
+
function Modal({ open, onClose, title, icon, copyText, size = "lg", dirty = false, onNext, onPrev, footer, bodyScroll, onMinimize, initialBox, actions, actionsLeft, allowPinOnTop, initialPosition, widget, compact, appStyle, autoHeight, autoMinHeight, widgetMenu, dimensions, windowKey, openedFromKey, children }) {
|
|
551
563
|
const isMobile = useIsMobile();
|
|
552
564
|
const [swipeX, setSwipeX] = useState(0);
|
|
553
565
|
const [swipeDragging, setSwipeDragging] = useState(false);
|
|
@@ -560,7 +572,9 @@ function Modal({ open, onClose, title, icon, copyText, size = "lg", dirty = fals
|
|
|
560
572
|
if (!isMobile) return;
|
|
561
573
|
swipeStartRef.current = { startX: e.clientX, startY: e.clientY, pointerId: e.pointerId };
|
|
562
574
|
setSwipeDragging(true);
|
|
563
|
-
|
|
575
|
+
setSwipingParentKey(openedFromKey ?? null);
|
|
576
|
+
}, [isMobile, openedFromKey]);
|
|
577
|
+
const swipingParentKey = useSyncExternalStore(subscribeSwipingParentKey, getSwipingParentKey);
|
|
564
578
|
useEffect(() => {
|
|
565
579
|
if (!swipeDragging) return;
|
|
566
580
|
const onMove = (ev) => {
|
|
@@ -571,6 +585,7 @@ function Modal({ open, onClose, title, icon, copyText, size = "lg", dirty = fals
|
|
|
571
585
|
swipeStartRef.current = null;
|
|
572
586
|
setSwipeDragging(false);
|
|
573
587
|
setSwipeX(0);
|
|
588
|
+
setSwipingParentKey(null);
|
|
574
589
|
return;
|
|
575
590
|
}
|
|
576
591
|
setSwipeX(Math.max(0, dx));
|
|
@@ -584,11 +599,13 @@ function Modal({ open, onClose, title, icon, copyText, size = "lg", dirty = fals
|
|
|
584
599
|
if (past) {
|
|
585
600
|
setSwipeX(window.innerWidth);
|
|
586
601
|
setTimeout(() => {
|
|
587
|
-
|
|
602
|
+
onClose();
|
|
588
603
|
setSwipeX(0);
|
|
604
|
+
setSwipingParentKey(null);
|
|
589
605
|
}, 180);
|
|
590
606
|
} else {
|
|
591
607
|
setSwipeX(0);
|
|
608
|
+
setSwipingParentKey(null);
|
|
592
609
|
}
|
|
593
610
|
};
|
|
594
611
|
window.addEventListener("pointermove", onMove);
|
|
@@ -1132,7 +1149,12 @@ function Modal({ open, onClose, title, icon, copyText, size = "lg", dirty = fals
|
|
|
1132
1149
|
},
|
|
1133
1150
|
style: isMobile ? {
|
|
1134
1151
|
// Mobile fullscreen: ignore stored box, fill viewport down to bottom
|
|
1135
|
-
// nav. Widgets stay hidden on mobile.
|
|
1152
|
+
// nav. Widgets stay hidden on mobile. Only the active window is
|
|
1153
|
+
// visible — all others hidden so swipe-right reveals the home
|
|
1154
|
+
// wallpaper backdrop. Exception: when a sibling Modal is being
|
|
1155
|
+
// swiped to-back and we're its `openedFrom` parent, un-hide so the
|
|
1156
|
+
// user sees their parent list during the slide instead of just the
|
|
1157
|
+
// wallpaper.
|
|
1136
1158
|
zIndex: zIndex + 1,
|
|
1137
1159
|
top: 0,
|
|
1138
1160
|
left: 0,
|
|
@@ -1143,14 +1165,18 @@ function Modal({ open, onClose, title, icon, copyText, size = "lg", dirty = fals
|
|
|
1143
1165
|
transform: `translateX(${swipeX}px)`,
|
|
1144
1166
|
transition: swipeDragging ? "none" : "transform 180ms ease-out",
|
|
1145
1167
|
...widget ? { display: "none" } : {},
|
|
1146
|
-
...zIndex < 0 ? { display: "none" } : {}
|
|
1168
|
+
...zIndex < 0 ? { display: "none" } : {},
|
|
1169
|
+
...!isActive && !pinnedOnTop && !(swipingParentKey && windowKey === swipingParentKey) ? { display: "none" } : {}
|
|
1147
1170
|
} : {
|
|
1148
1171
|
zIndex: pinnedOnTop ? 999 : zIndex + 1,
|
|
1149
1172
|
width: box.w,
|
|
1150
1173
|
height: autoHeight ? "auto" : box.h,
|
|
1151
1174
|
top: box.y,
|
|
1152
1175
|
...autoHeight ? {
|
|
1153
|
-
|
|
1176
|
+
// Widgets must fit content exactly (Weather, Currency, etc.) —
|
|
1177
|
+
// the 240 px floor only applies to non-widget app windows where
|
|
1178
|
+
// a near-empty body would look broken.
|
|
1179
|
+
minHeight: `${autoMinHeight ?? (widget ? 0 : 240)}px`,
|
|
1154
1180
|
maxHeight: `calc(100vh - var(--taskbar-height, 0px) - 24px)`
|
|
1155
1181
|
} : {},
|
|
1156
1182
|
...widget && widgetAnchor === "right" ? { right: window.innerWidth - box.x - box.w } : { left: box.x },
|
|
@@ -1434,7 +1460,7 @@ function useWindowManager() {
|
|
|
1434
1460
|
}
|
|
1435
1461
|
function DesktopShortcutMenuItem({ item }) {
|
|
1436
1462
|
const queryClient = useQueryClient();
|
|
1437
|
-
const { data: profile } = useQuery({ queryKey: ["my-profile-sidebar"], queryFn: () => client_default.get("/auth/me/").then((r) => r.data) });
|
|
1463
|
+
const { data: profile } = useQuery({ queryKey: ["my-profile-sidebar"], enabled: isShellApiClientConfigured(), queryFn: () => client_default.get("/auth/me/").then((r) => r.data) });
|
|
1438
1464
|
const favDocs = (profile?.preferences || {}).favorite_documents || [];
|
|
1439
1465
|
const favType = item.type === "page" ? "page" : item.entityType || "";
|
|
1440
1466
|
const favId = item.type === "page" ? item.route || "" : item.entityId || "";
|
|
@@ -1454,14 +1480,14 @@ function PageWindow({ item, onClose }) {
|
|
|
1454
1480
|
if (!raw || !isPageEntry(raw)) return null;
|
|
1455
1481
|
const entry = raw;
|
|
1456
1482
|
const Component = entry.component;
|
|
1457
|
-
return /* @__PURE__ */ jsxs(Modal, { open: true, onClose, icon: navIcons[item.route], title: entry.label, size: entry.size || "2xl", allowPinOnTop: entry.allowPinOnTop, initialPosition: entry.initialPosition, widget: entry.widget, compact: entry.compact, appStyle: entry.appStyle, autoHeight: entry.autoHeight, autoMinHeight: entry.autoMinHeight, dimensions: entry.dimensions, windowKey: item.id, children: [
|
|
1483
|
+
return /* @__PURE__ */ jsxs(Modal, { open: true, onClose, icon: navIcons[item.route], title: entry.label, size: entry.size || "2xl", allowPinOnTop: entry.allowPinOnTop, initialPosition: entry.initialPosition, widget: entry.widget, compact: entry.compact, appStyle: entry.appStyle, autoHeight: entry.autoHeight, autoMinHeight: entry.autoMinHeight, dimensions: entry.dimensions, windowKey: item.id, openedFromKey: item.openedFrom, children: [
|
|
1458
1484
|
/* @__PURE__ */ jsx(DesktopShortcutMenuItem, { item }),
|
|
1459
1485
|
/* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsx(LoadingSpinner, {}) }), children: /* @__PURE__ */ jsx(Component, {}) })
|
|
1460
1486
|
] });
|
|
1461
1487
|
}
|
|
1462
1488
|
function DocFavStar({ entityType, entityId, label }) {
|
|
1463
1489
|
const queryClient = useQueryClient();
|
|
1464
|
-
const { data: profile } = useQuery({ queryKey: ["my-profile-sidebar"], queryFn: () => client_default.get("/auth/me/").then((r) => r.data) });
|
|
1490
|
+
const { data: profile } = useQuery({ queryKey: ["my-profile-sidebar"], enabled: isShellApiClientConfigured(), queryFn: () => client_default.get("/auth/me/").then((r) => r.data) });
|
|
1465
1491
|
const favDocs = (profile?.preferences || {}).favorite_documents || [];
|
|
1466
1492
|
const isFav = favDocs.some((d) => d.entityType === entityType && d.entityId === entityId);
|
|
1467
1493
|
const toggle = () => {
|
|
@@ -1493,7 +1519,7 @@ function RestoredRegistryModal({ item, onClose, onMinimize }) {
|
|
|
1493
1519
|
initialData: item.entitySnapshot,
|
|
1494
1520
|
initialDataUpdatedAt: 0,
|
|
1495
1521
|
// Treat snapshot as stale so query refetches immediately
|
|
1496
|
-
enabled: !entry.selfFetching && !isDuplicate,
|
|
1522
|
+
enabled: !entry.selfFetching && !isDuplicate && isShellApiClientConfigured(),
|
|
1497
1523
|
staleTime: 0,
|
|
1498
1524
|
refetchOnWindowFocus: true,
|
|
1499
1525
|
refetchOnMount: "always",
|
|
@@ -1539,6 +1565,7 @@ function RestoredRegistryModal({ item, onClose, onMinimize }) {
|
|
|
1539
1565
|
footer: footerContent,
|
|
1540
1566
|
copyText: item.id,
|
|
1541
1567
|
windowKey: item.id,
|
|
1568
|
+
openedFromKey: item.openedFrom,
|
|
1542
1569
|
size: entry.size || "2xl",
|
|
1543
1570
|
autoHeight: entry.autoHeight,
|
|
1544
1571
|
autoMinHeight: entry.autoMinHeight,
|
|
@@ -1553,6 +1580,12 @@ function RestoredRegistryModal({ item, onClose, onMinimize }) {
|
|
|
1553
1580
|
function findPanelByWindowKey(key) {
|
|
1554
1581
|
return document.querySelector(`[data-modal-panel][data-window-key="${key}"]`);
|
|
1555
1582
|
}
|
|
1583
|
+
function currentlyActiveWindowKey() {
|
|
1584
|
+
const activeId = getActiveModalId();
|
|
1585
|
+
if (!activeId) return void 0;
|
|
1586
|
+
const panel = document.querySelector(`[data-modal-panel][data-modal-id="${activeId}"]`);
|
|
1587
|
+
return panel?.getAttribute("data-window-key") ?? void 0;
|
|
1588
|
+
}
|
|
1556
1589
|
function findPanelByLabel(label) {
|
|
1557
1590
|
const panels = document.querySelectorAll("[data-modal-panel]");
|
|
1558
1591
|
for (const p of Array.from(panels)) {
|
|
@@ -1684,7 +1717,7 @@ function TaskbarTabPreview({ items, anchorEl, onActivate, onClose, onMouseEnter,
|
|
|
1684
1717
|
maxWidth: "calc(100vw - 16px)",
|
|
1685
1718
|
opacity: pos.ready ? 1 : 0
|
|
1686
1719
|
},
|
|
1687
|
-
className: isGroup ? "flex gap-2
|
|
1720
|
+
className: isGroup ? "flex gap-2 flex-wrap" : "",
|
|
1688
1721
|
onMouseEnter,
|
|
1689
1722
|
onMouseLeave,
|
|
1690
1723
|
children: items.map((it) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center", children: [
|
|
@@ -1898,6 +1931,7 @@ function WindowManagerProvider({ children }) {
|
|
|
1898
1931
|
const openEntity = useCallback((entityType, entityId, snapshot, label, route) => {
|
|
1899
1932
|
if (!WINDOW_REGISTRY[entityType] || !isEntityEntry(WINDOW_REGISTRY[entityType])) return;
|
|
1900
1933
|
const id = label || entityId;
|
|
1934
|
+
const openedFrom = currentlyActiveWindowKey();
|
|
1901
1935
|
setOpenWindows((prev) => {
|
|
1902
1936
|
const existing = prev.find((m) => m.entityId === entityId && m.entityType === entityType);
|
|
1903
1937
|
if (existing) {
|
|
@@ -1920,13 +1954,15 @@ function WindowManagerProvider({ children }) {
|
|
|
1920
1954
|
route: route || window.location.pathname,
|
|
1921
1955
|
entityType,
|
|
1922
1956
|
entityId,
|
|
1923
|
-
entitySnapshot: snapshot
|
|
1957
|
+
entitySnapshot: snapshot,
|
|
1958
|
+
openedFrom
|
|
1924
1959
|
}];
|
|
1925
1960
|
});
|
|
1926
1961
|
}, []);
|
|
1927
1962
|
const openPage = useCallback((path) => {
|
|
1928
1963
|
if (!WINDOW_REGISTRY[path] || !isPageEntry(WINDOW_REGISTRY[path])) return;
|
|
1929
1964
|
const entry = WINDOW_REGISTRY[path];
|
|
1965
|
+
const openedFrom = currentlyActiveWindowKey();
|
|
1930
1966
|
setOpenWindows((prev) => {
|
|
1931
1967
|
if (entry.multiInstance) {
|
|
1932
1968
|
const instanceCount = prev.filter((m) => m.type === "page" && m.route === path).length;
|
|
@@ -1936,7 +1972,8 @@ function WindowManagerProvider({ children }) {
|
|
|
1936
1972
|
id,
|
|
1937
1973
|
type: "page",
|
|
1938
1974
|
label: instanceCount === 0 ? entry.label : `${entry.label} ${nextNum}`,
|
|
1939
|
-
route: path
|
|
1975
|
+
route: path,
|
|
1976
|
+
openedFrom
|
|
1940
1977
|
}];
|
|
1941
1978
|
}
|
|
1942
1979
|
const existing = prev.find((m) => m.type === "page" && m.route === path);
|
|
@@ -1960,7 +1997,8 @@ function WindowManagerProvider({ children }) {
|
|
|
1960
1997
|
id: `page:${path}`,
|
|
1961
1998
|
type: "page",
|
|
1962
1999
|
label: entry.label,
|
|
1963
|
-
route: path
|
|
2000
|
+
route: path,
|
|
2001
|
+
openedFrom
|
|
1964
2002
|
}];
|
|
1965
2003
|
});
|
|
1966
2004
|
}, []);
|
|
@@ -2009,6 +2047,6 @@ function WindowManagerProvider({ children }) {
|
|
|
2009
2047
|
] });
|
|
2010
2048
|
}
|
|
2011
2049
|
|
|
2012
|
-
export { CancelButton, CopyButton, DocFavStar, GLASS_DIVIDER, GLASS_INPUT_BG, LoadingSpinner, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, ThumbCard, WINDOW_REGISTRY, WindowManagerProvider, WindowTitle, activateModal, client_default, getActiveModalId,
|
|
2013
|
-
//# sourceMappingURL=chunk-
|
|
2014
|
-
//# sourceMappingURL=chunk-
|
|
2050
|
+
export { CancelButton, CopyButton, DocFavStar, GLASS_DIVIDER, GLASS_INPUT_BG, LoadingSpinner, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, ThumbCard, WINDOW_REGISTRY, WindowManagerProvider, WindowTitle, activateModal, client_default, getActiveModalId, glassStyle, isEntityEntry, isPageEntry, isSection, navIcons, navSections, sectionIcons, setShellApiClient, setShellNavIcons, setShellWindowRegistry, startMenuCategories, useIsMobile, useModalActive, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle };
|
|
2051
|
+
//# sourceMappingURL=chunk-QXY6ZHRX.js.map
|
|
2052
|
+
//# sourceMappingURL=chunk-QXY6ZHRX.js.map
|