react-os-shell 3.28.3 → 4.0.2
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-OE4RRSNX.js → Browser-URIWHULK.js} +5 -5
- package/dist/{Browser-OE4RRSNX.js.map → Browser-URIWHULK.js.map} +1 -1
- package/dist/{Calculator-BJGIBI4Y.js → Calculator-6DY3KD2Y.js} +4 -4
- package/dist/{Calculator-BJGIBI4Y.js.map → Calculator-6DY3KD2Y.js.map} +1 -1
- package/dist/ConfirmDialog-KCBMXGXD.js +4 -0
- package/dist/{ConfirmDialog-LPE2X6OJ.js.map → ConfirmDialog-KCBMXGXD.js.map} +1 -1
- package/dist/{CurrencyConverter-CHTBKF6J.js → CurrencyConverter-OJDKNEKD.js} +4 -4
- package/dist/{CurrencyConverter-CHTBKF6J.js.map → CurrencyConverter-OJDKNEKD.js.map} +1 -1
- package/dist/{Documents-D6Q75QR7.js → Documents-6Q337VVX.js} +5 -5
- package/dist/{Documents-D6Q75QR7.js.map → Documents-6Q337VVX.js.map} +1 -1
- package/dist/{Files-ROREKNZQ.js → Files-FGDT4FXU.js} +7 -7
- package/dist/{Files-ROREKNZQ.js.map → Files-FGDT4FXU.js.map} +1 -1
- package/dist/{Notepad-5P66KO2D.js → Notepad-PDBAFURQ.js} +5 -5
- package/dist/{Notepad-5P66KO2D.js.map → Notepad-PDBAFURQ.js.map} +1 -1
- package/dist/{PomodoroTimer-NLIPU5UR.js → PomodoroTimer-42TV6ZGY.js} +5 -5
- package/dist/{PomodoroTimer-NLIPU5UR.js.map → PomodoroTimer-42TV6ZGY.js.map} +1 -1
- package/dist/{Preview-7F27UNJW.js → Preview-KW7B6M5Z.js} +5 -5
- package/dist/{Preview-7F27UNJW.js.map → Preview-KW7B6M5Z.js.map} +1 -1
- package/dist/{Spreadsheet-NKJBGBWK.js → Spreadsheet-NRBZK7K7.js} +5 -5
- package/dist/{Spreadsheet-NKJBGBWK.js.map → Spreadsheet-NRBZK7K7.js.map} +1 -1
- package/dist/{Stock-Q5TKAAYK.js → Stock-V3IXTXM5.js} +4 -4
- package/dist/{Stock-Q5TKAAYK.js.map → Stock-V3IXTXM5.js.map} +1 -1
- package/dist/{Weather-ZZBMC3TS.js → Weather-TP2Z6ZWJ.js} +4 -4
- package/dist/{Weather-ZZBMC3TS.js.map → Weather-TP2Z6ZWJ.js.map} +1 -1
- package/dist/{WorldClock-ILLIOFRX.js → WorldClock-HE52XN6O.js} +4 -4
- package/dist/{WorldClock-ILLIOFRX.js.map → WorldClock-HE52XN6O.js.map} +1 -1
- package/dist/apps/index.js +17 -17
- package/dist/{chunk-WCV2646Z.js → chunk-5MEYTQUU.js} +4 -4
- package/dist/{chunk-WCV2646Z.js.map → chunk-5MEYTQUU.js.map} +1 -1
- package/dist/chunk-5S7UOT43.js +7 -0
- package/dist/{chunk-KFJA5CYZ.js.map → chunk-5S7UOT43.js.map} +1 -1
- package/dist/{chunk-7GNI7HRH.js → chunk-BU4ZUYWM.js} +3 -3
- package/dist/{chunk-7GNI7HRH.js.map → chunk-BU4ZUYWM.js.map} +1 -1
- package/dist/{chunk-6LMWM4ZE.js → chunk-HXH6P73V.js} +9 -8
- package/dist/chunk-HXH6P73V.js.map +1 -0
- package/dist/{chunk-LRVPNWRE.js → chunk-QXWBHX7J.js} +3 -3
- package/dist/chunk-QXWBHX7J.js.map +1 -0
- package/dist/{chunk-AA24QYTD.js → chunk-RVUMXSQE.js} +3 -3
- package/dist/{chunk-AA24QYTD.js.map → chunk-RVUMXSQE.js.map} +1 -1
- package/dist/{chunk-AKPD4Z34.js → chunk-SVOHTHJQ.js} +3 -3
- package/dist/{chunk-AKPD4Z34.js.map → chunk-SVOHTHJQ.js.map} +1 -1
- package/dist/index.d.ts +20 -2
- package/dist/index.js +50 -755
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/ConfirmDialog-LPE2X6OJ.js +0 -4
- package/dist/chunk-6LMWM4ZE.js.map +0 -1
- package/dist/chunk-KFJA5CYZ.js +0 -7
- package/dist/chunk-LRVPNWRE.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { subscribePomo, getPomoSnapshot } from './chunk-
|
|
2
|
-
export { setShellTodoProvider } from './chunk-
|
|
1
|
+
import { subscribePomo, getPomoSnapshot } from './chunk-SVOHTHJQ.js';
|
|
2
|
+
export { setShellTodoProvider } from './chunk-SVOHTHJQ.js';
|
|
3
3
|
export { ImageAnnotator_default as ImageAnnotator } from './chunk-QU5L5ZYM.js';
|
|
4
4
|
import { PREVIEW_OPENED_EVENT, openPreviewFile } from './chunk-DINNWYVB.js';
|
|
5
5
|
export { Breadcrumbs } from './chunk-DINNWYVB.js';
|
|
@@ -7,7 +7,7 @@ import { SidebarLayout } from './chunk-YG45DAUT.js';
|
|
|
7
7
|
export { SidebarLayout } from './chunk-YG45DAUT.js';
|
|
8
8
|
import { toast_default } from './chunk-VENYVK3L.js';
|
|
9
9
|
export { toast_default as toast } from './chunk-VENYVK3L.js';
|
|
10
|
-
import { publishDesktopFolders, requestFilesTrashView, FolderGlyph, requestFilesDesktopFolderView, FileIconTile
|
|
10
|
+
import { publishDesktopFolders, requestFilesTrashView, FolderGlyph, requestFilesDesktopFolderView, FileIconTile } from './chunk-QXWBHX7J.js';
|
|
11
11
|
import { setPdfPreview } from './chunk-BV6SQ46N.js';
|
|
12
12
|
import { playNotification, playStartup, soundsEnabled, getSoundConfig, SOUND_PACK_KEYS, SOUND_PACKS, SOUND_TYPES, SOUND_TYPE_LABELS, setSoundForType, previewSound, setAllSounds, playLogout } from './chunk-D7PYW2QS.js';
|
|
13
13
|
import { useAuth, useShellAuth } from './chunk-ADJ3CERD.js';
|
|
@@ -15,10 +15,10 @@ export { ShellAuthProvider, setShellAuthBridge, useShellAuth } from './chunk-ADJ
|
|
|
15
15
|
import { EditableGrid } from './chunk-GP4Y3VCB.js';
|
|
16
16
|
export { EditableGrid } from './chunk-GP4Y3VCB.js';
|
|
17
17
|
import './chunk-4SQU5YV6.js';
|
|
18
|
-
import { APP_VERSION, VERSION } from './chunk-
|
|
19
|
-
export { VERSION } from './chunk-
|
|
20
|
-
import { registerModalEscapeInterceptor, useIsMobile, useWindowManager, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, WINDOW_REGISTRY, isPageEntry, Modal, useShellPrefs, SIDEBAR_STRIP_W, forgetMaximizedWindowBoxes, ModalActions, useModalActive, client_default, LoadingSpinner, isShellApiClientConfigured, CancelButton, setWindowPosition
|
|
21
|
-
export { CancelButton, ConfirmProvider, CopyButton, DocFavStar, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, ShellPrefsProvider, WindowCrashedFallback, WindowErrorBoundary, WindowManagerProvider, WindowTitle, commitExposeHighlight, confirm, confirmDestructive, exitExposeMode, getActiveWindowRoute, getExposeHighlight, getWindowPosition, isEntityEntry, isPageEntry, prompt, registerModalEscapeInterceptor, setExposeHighlight, setShellApiClient, setShellWindowRegistry, setWindowDefaultPosition, setWindowPosition, subscribeExposeHighlight, toggleExposeMode, useLocalStoragePrefs, useModalActive, useShellPrefs, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-
|
|
18
|
+
import { APP_VERSION, VERSION } from './chunk-5S7UOT43.js';
|
|
19
|
+
export { VERSION } from './chunk-5S7UOT43.js';
|
|
20
|
+
import { registerModalEscapeInterceptor, useIsMobile, useWindowManager, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, WINDOW_REGISTRY, isPageEntry, Modal, useShellPrefs, SIDEBAR_STRIP_W, forgetMaximizedWindowBoxes, ModalActions, useModalActive, client_default, LoadingSpinner, isShellApiClientConfigured, CancelButton, setWindowPosition } from './chunk-HXH6P73V.js';
|
|
21
|
+
export { CancelButton, ConfirmProvider, CopyButton, DocFavStar, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, ShellPrefsProvider, WindowCrashedFallback, WindowErrorBoundary, WindowManagerProvider, WindowTitle, commitExposeHighlight, confirm, confirmDestructive, exitExposeMode, getActiveWindowRoute, getExposeHighlight, getWindowPosition, isEntityEntry, isPageEntry, prompt, registerModalEscapeInterceptor, setExposeHighlight, setShellApiClient, setShellWindowRegistry, setWindowDefaultPosition, setWindowPosition, subscribeExposeHighlight, toggleExposeMode, useLocalStoragePrefs, useModalActive, useShellPrefs, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-HXH6P73V.js';
|
|
22
22
|
import { glassStyle, startMenuCategories, navSections, isSection, GLASS_INPUT_BG, navIcons, sectionIcons } from './chunk-GW3RA6IS.js';
|
|
23
23
|
export { GLASS_DIVIDER, GLASS_INPUT_BG, glassStyle, setShellNavIcons } from './chunk-GW3RA6IS.js';
|
|
24
24
|
import { createContext, lazy, forwardRef, useCallback, useState, useRef, useId, useEffect, useLayoutEffect, useMemo, useContext, isValidElement, cloneElement, Suspense, Fragment as Fragment$1, Children, useSyncExternalStore } from 'react';
|
|
@@ -3340,744 +3340,45 @@ function StartMenu({
|
|
|
3340
3340
|
] })
|
|
3341
3341
|
);
|
|
3342
3342
|
}
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
return _mode;
|
|
3349
|
-
}
|
|
3350
|
-
function setMobileMode(mode) {
|
|
3351
|
-
if (_mode === mode) return;
|
|
3352
|
-
_mode = mode;
|
|
3353
|
-
listeners.forEach((fn) => fn());
|
|
3354
|
-
}
|
|
3355
|
-
function subscribeMobileMode(cb) {
|
|
3356
|
-
listeners.add(cb);
|
|
3357
|
-
return () => {
|
|
3358
|
-
listeners.delete(cb);
|
|
3359
|
-
};
|
|
3360
|
-
}
|
|
3361
|
-
var MOBILE_WIDGET_ORDER_KEY = "erp_mobile_widget_order";
|
|
3362
|
-
var MOBILE_HOME_ORDER_KEY = "erp_mobile_home_order";
|
|
3363
|
-
var LONG_PRESS_MS = 400;
|
|
3364
|
-
function loadOrder(key) {
|
|
3365
|
-
try {
|
|
3366
|
-
const raw = localStorage.getItem(key);
|
|
3367
|
-
if (raw) {
|
|
3368
|
-
const parsed = JSON.parse(raw);
|
|
3369
|
-
if (Array.isArray(parsed)) return parsed.filter((s) => typeof s === "string");
|
|
3370
|
-
}
|
|
3371
|
-
} catch {
|
|
3372
|
-
}
|
|
3373
|
-
return [];
|
|
3374
|
-
}
|
|
3375
|
-
function saveOrder(key, order) {
|
|
3376
|
-
try {
|
|
3377
|
-
localStorage.setItem(key, JSON.stringify(order));
|
|
3378
|
-
} catch {
|
|
3379
|
-
}
|
|
3380
|
-
}
|
|
3381
|
-
var FALLBACK_APP_ICON = /* @__PURE__ */ jsx("svg", { className: "h-10 w-10", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3.75 6.75A2.25 2.25 0 016 4.5h12a2.25 2.25 0 012.25 2.25v10.5A2.25 2.25 0 0118 19.5H6a2.25 2.25 0 01-2.25-2.25V6.75z" }) });
|
|
3382
|
-
function sizeIcon(node, fallback, sizeClass = "h-10 w-10") {
|
|
3383
|
-
if (!node) return fallback;
|
|
3384
|
-
if (isValidElement(node)) {
|
|
3385
|
-
return cloneElement(node, {
|
|
3386
|
-
className: `${sizeClass} ${node.props?.className ?? ""}`.trim()
|
|
3387
|
-
});
|
|
3388
|
-
}
|
|
3389
|
-
return node;
|
|
3390
|
-
}
|
|
3391
|
-
function AppTile({ route, icon }) {
|
|
3392
|
-
return /* @__PURE__ */ jsx("span", { className: `relative aspect-square w-full rounded-2xl bg-gradient-to-br ${hashGradient(route)} flex items-center justify-center text-white shadow-sm border border-white/30`, children: sizeIcon(icon, FALLBACK_APP_ICON, "h-11 w-11") });
|
|
3393
|
-
}
|
|
3394
|
-
function FolderTile({ section, navIcons: navIcons2 }) {
|
|
3395
|
-
const previewItems = section.items.slice(0, 4);
|
|
3396
|
-
return /* @__PURE__ */ jsxs("span", { className: "relative aspect-square w-full rounded-2xl bg-white/30 backdrop-blur-sm border border-white/40 p-1.5 grid grid-cols-2 gap-1 shadow-sm", children: [
|
|
3397
|
-
previewItems.map((item) => /* @__PURE__ */ jsx(
|
|
3398
|
-
"span",
|
|
3399
|
-
{
|
|
3400
|
-
className: `rounded-md bg-gradient-to-br ${hashGradient(item.to)} flex items-center justify-center text-white`,
|
|
3401
|
-
children: sizeIcon(navIcons2[item.to], FALLBACK_APP_ICON, "h-3.5 w-3.5")
|
|
3402
|
-
},
|
|
3403
|
-
item.to
|
|
3404
|
-
)),
|
|
3405
|
-
Array.from({ length: Math.max(0, 4 - previewItems.length) }).map((_, i) => /* @__PURE__ */ jsx("span", { className: "rounded-md bg-white/20" }, `empty-${i}`))
|
|
3406
|
-
] });
|
|
3407
|
-
}
|
|
3408
|
-
function MobileHome({
|
|
3409
|
-
navSections: navSections2,
|
|
3410
|
-
navIcons: navIcons2,
|
|
3411
|
-
sectionIcons: sectionIcons2,
|
|
3412
|
-
openWindows,
|
|
3413
|
-
onOpenApp,
|
|
3414
|
-
onActivateWindow
|
|
3415
|
-
}) {
|
|
3416
|
-
const [selectedFolder, setSelectedFolder] = useState(null);
|
|
3417
|
-
const homeIconsRaw = useMemo(() => {
|
|
3418
|
-
const list = [];
|
|
3419
|
-
for (const entry of navSections2) {
|
|
3420
|
-
if (isSection(entry)) {
|
|
3421
|
-
const sec = entry;
|
|
3422
|
-
list.push({ kind: "folder", id: `folder:${sec.label}`, label: sec.label, section: sec });
|
|
3423
|
-
} else {
|
|
3424
|
-
const it = entry;
|
|
3425
|
-
list.push({ kind: "app", id: `app:${it.to}`, label: it.label, route: it.to });
|
|
3426
|
-
}
|
|
3427
|
-
}
|
|
3428
|
-
return list;
|
|
3429
|
-
}, [navSections2]);
|
|
3430
|
-
const [homeOrder, setHomeOrder] = useState(() => loadOrder(MOBILE_HOME_ORDER_KEY));
|
|
3431
|
-
const homeIcons = useMemo(() => {
|
|
3432
|
-
const indexFor = (id) => {
|
|
3433
|
-
const i = homeOrder.indexOf(id);
|
|
3434
|
-
return i === -1 ? Number.MAX_SAFE_INTEGER : i;
|
|
3435
|
-
};
|
|
3436
|
-
return homeIconsRaw.slice().sort((a, b) => {
|
|
3437
|
-
const ia = indexFor(a.id);
|
|
3438
|
-
const ib = indexFor(b.id);
|
|
3439
|
-
if (ia !== ib) return ia - ib;
|
|
3440
|
-
return homeIconsRaw.indexOf(a) - homeIconsRaw.indexOf(b);
|
|
3441
|
-
});
|
|
3442
|
-
}, [homeIconsRaw, homeOrder]);
|
|
3443
|
-
useEffect(() => {
|
|
3444
|
-
const visibleIds = homeIconsRaw.map((i) => i.id);
|
|
3445
|
-
const next = [
|
|
3446
|
-
...homeOrder.filter((id) => visibleIds.includes(id)),
|
|
3447
|
-
...visibleIds.filter((id) => !homeOrder.includes(id))
|
|
3448
|
-
];
|
|
3449
|
-
if (next.length !== homeOrder.length || next.some((id, i) => id !== homeOrder[i])) {
|
|
3450
|
-
setHomeOrder(next);
|
|
3451
|
-
saveOrder(MOBILE_HOME_ORDER_KEY, next);
|
|
3452
|
-
}
|
|
3453
|
-
}, [homeIconsRaw, homeOrder]);
|
|
3454
|
-
const [dragId, setDragId] = useState(null);
|
|
3455
|
-
const [dragPos, setDragPos] = useState(null);
|
|
3456
|
-
const dragOffsetRef = useRef({ x: 0, y: 0 });
|
|
3457
|
-
const longPressTimerRef = useRef(null);
|
|
3458
|
-
const longPressFiredRef = useRef(false);
|
|
3459
|
-
const cancelLongPress = () => {
|
|
3460
|
-
if (longPressTimerRef.current) {
|
|
3461
|
-
clearTimeout(longPressTimerRef.current);
|
|
3462
|
-
longPressTimerRef.current = null;
|
|
3463
|
-
}
|
|
3464
|
-
};
|
|
3465
|
-
const beginLongPress = (id, e) => {
|
|
3466
|
-
if (dragId) return;
|
|
3467
|
-
const x = e.clientX;
|
|
3468
|
-
const y = e.clientY;
|
|
3469
|
-
const target = e.currentTarget;
|
|
3470
|
-
longPressFiredRef.current = false;
|
|
3471
|
-
cancelLongPress();
|
|
3472
|
-
longPressTimerRef.current = setTimeout(() => {
|
|
3473
|
-
if (!target.isConnected) return;
|
|
3474
|
-
const rect = target.getBoundingClientRect();
|
|
3475
|
-
dragOffsetRef.current = { x: x - rect.left, y: y - rect.top };
|
|
3476
|
-
longPressFiredRef.current = true;
|
|
3477
|
-
setDragId(id);
|
|
3478
|
-
setDragPos({ x, y });
|
|
3479
|
-
try {
|
|
3480
|
-
navigator.vibrate?.(15);
|
|
3481
|
-
} catch {
|
|
3482
|
-
}
|
|
3483
|
-
}, LONG_PRESS_MS);
|
|
3484
|
-
};
|
|
3485
|
-
useEffect(() => {
|
|
3486
|
-
if (!dragId) return;
|
|
3487
|
-
const onMove = (e) => {
|
|
3488
|
-
setDragPos({ x: e.clientX, y: e.clientY });
|
|
3489
|
-
const el = document.elementFromPoint(e.clientX, e.clientY);
|
|
3490
|
-
const targetEl = el?.closest("[data-home-icon-id]");
|
|
3491
|
-
if (!targetEl) return;
|
|
3492
|
-
const targetId = targetEl.dataset.homeIconId;
|
|
3493
|
-
if (targetId === dragId) return;
|
|
3494
|
-
setHomeOrder((prev) => {
|
|
3495
|
-
const fromIdx = prev.indexOf(dragId);
|
|
3496
|
-
const toIdx = prev.indexOf(targetId);
|
|
3497
|
-
if (fromIdx === -1 || toIdx === -1) return prev;
|
|
3498
|
-
const next = prev.slice();
|
|
3499
|
-
next.splice(fromIdx, 1);
|
|
3500
|
-
next.splice(toIdx, 0, dragId);
|
|
3501
|
-
return next;
|
|
3502
|
-
});
|
|
3503
|
-
};
|
|
3504
|
-
const onUp = () => {
|
|
3505
|
-
setDragId(null);
|
|
3506
|
-
setDragPos(null);
|
|
3507
|
-
setHomeOrder((prev) => {
|
|
3508
|
-
saveOrder(MOBILE_HOME_ORDER_KEY, prev);
|
|
3509
|
-
return prev;
|
|
3510
|
-
});
|
|
3511
|
-
};
|
|
3512
|
-
window.addEventListener("pointermove", onMove);
|
|
3513
|
-
window.addEventListener("pointerup", onUp);
|
|
3514
|
-
window.addEventListener("pointercancel", onUp);
|
|
3515
|
-
return () => {
|
|
3516
|
-
window.removeEventListener("pointermove", onMove);
|
|
3517
|
-
window.removeEventListener("pointerup", onUp);
|
|
3518
|
-
window.removeEventListener("pointercancel", onUp);
|
|
3519
|
-
};
|
|
3520
|
-
}, [dragId]);
|
|
3521
|
-
const handleIconClick = (icon) => {
|
|
3522
|
-
if (longPressFiredRef.current) {
|
|
3523
|
-
longPressFiredRef.current = false;
|
|
3524
|
-
return;
|
|
3525
|
-
}
|
|
3526
|
-
if (icon.kind === "app") onOpenApp(icon.route);
|
|
3527
|
-
else setSelectedFolder(icon.section);
|
|
3528
|
-
};
|
|
3529
|
-
const [widgetOrder, _setWidgetOrder] = useState(() => loadOrder(MOBILE_WIDGET_ORDER_KEY));
|
|
3530
|
-
const widgetWindows = useMemo(() => {
|
|
3531
|
-
const widgets = openWindows.filter((w) => {
|
|
3532
|
-
if (!w.route) return false;
|
|
3533
|
-
const entry = WINDOW_REGISTRY[w.route];
|
|
3534
|
-
return entry && isPageEntry(entry) && entry.widget;
|
|
3535
|
-
});
|
|
3536
|
-
const indexFor = (route) => {
|
|
3537
|
-
const i = widgetOrder.indexOf(route);
|
|
3538
|
-
return i === -1 ? Number.MAX_SAFE_INTEGER : i;
|
|
3539
|
-
};
|
|
3540
|
-
return widgets.slice().sort((a, b) => indexFor(a.route) - indexFor(b.route));
|
|
3541
|
-
}, [openWindows, widgetOrder]);
|
|
3542
|
-
useEffect(() => {
|
|
3543
|
-
const visibleRoutes = widgetWindows.map((w) => w.route).filter(Boolean);
|
|
3544
|
-
const next = [
|
|
3545
|
-
...widgetOrder.filter((r) => visibleRoutes.includes(r)),
|
|
3546
|
-
...visibleRoutes.filter((r) => !widgetOrder.includes(r))
|
|
3547
|
-
];
|
|
3548
|
-
if (next.length !== widgetOrder.length || next.some((r, i) => r !== widgetOrder[i])) {
|
|
3549
|
-
_setWidgetOrder(next);
|
|
3550
|
-
saveOrder(MOBILE_WIDGET_ORDER_KEY, next);
|
|
3551
|
-
}
|
|
3552
|
-
}, [widgetWindows, widgetOrder]);
|
|
3553
|
-
useMemo(() => {
|
|
3554
|
-
const map = /* @__PURE__ */ new Map();
|
|
3555
|
-
for (const w of openWindows) {
|
|
3556
|
-
if (!w.route) continue;
|
|
3557
|
-
map.set(w.route, (map.get(w.route) ?? 0) + 1);
|
|
3558
|
-
}
|
|
3559
|
-
return map;
|
|
3560
|
-
}, [openWindows]);
|
|
3561
|
-
const draggedIcon = dragId ? homeIcons.find((i) => i.id === dragId) : null;
|
|
3562
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3563
|
-
/* @__PURE__ */ jsx(
|
|
3564
|
-
"div",
|
|
3565
|
-
{
|
|
3566
|
-
className: "h-full overflow-y-auto px-4 pt-4 pb-4 select-none",
|
|
3567
|
-
style: {
|
|
3568
|
-
// Disable iOS long-press text-selection / "Copy" callout on icon labels.
|
|
3569
|
-
WebkitUserSelect: "none",
|
|
3570
|
-
WebkitTouchCallout: "none"
|
|
3571
|
-
},
|
|
3572
|
-
children: /* @__PURE__ */ jsxs("div", { children: [
|
|
3573
|
-
widgetWindows.length > 0 && /* @__PURE__ */ jsx("section", { className: "mb-4", children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-4 gap-4", children: widgetWindows.map((w) => {
|
|
3574
|
-
const entry = WINDOW_REGISTRY[w.route];
|
|
3575
|
-
if (!entry) return null;
|
|
3576
|
-
const Component = entry.component;
|
|
3577
|
-
return /* @__PURE__ */ jsx(
|
|
3578
|
-
"div",
|
|
3579
|
-
{
|
|
3580
|
-
className: "col-span-2 relative rounded-2xl bg-white/85 backdrop-blur border border-white/40 shadow-md overflow-hidden aspect-square",
|
|
3581
|
-
children: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ jsx(LoadingSpinner, {}) }), children: /* @__PURE__ */ jsx(Component, {}) })
|
|
3582
|
-
},
|
|
3583
|
-
w.id
|
|
3584
|
-
);
|
|
3585
|
-
}) }) }),
|
|
3586
|
-
homeIcons.length > 0 && /* @__PURE__ */ jsx("section", { children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-4 gap-4", children: homeIcons.map((icon) => {
|
|
3587
|
-
const isFolder = icon.kind === "folder";
|
|
3588
|
-
const isBeingDragged = dragId === icon.id;
|
|
3589
|
-
return /* @__PURE__ */ jsxs(
|
|
3590
|
-
"button",
|
|
3591
|
-
{
|
|
3592
|
-
"data-home-icon-id": icon.id,
|
|
3593
|
-
onPointerDown: (e) => beginLongPress(icon.id, e),
|
|
3594
|
-
onPointerUp: cancelLongPress,
|
|
3595
|
-
onPointerCancel: cancelLongPress,
|
|
3596
|
-
onPointerLeave: cancelLongPress,
|
|
3597
|
-
onClick: () => handleIconClick(icon),
|
|
3598
|
-
style: { touchAction: "none", visibility: isBeingDragged ? "hidden" : "visible" },
|
|
3599
|
-
className: `flex flex-col items-center gap-1 py-1 rounded-lg active:bg-white/20 ${dragId && !isBeingDragged ? "transition-transform" : ""}`,
|
|
3600
|
-
children: [
|
|
3601
|
-
isFolder ? /* @__PURE__ */ jsx(FolderTile, { section: icon.section, navIcons: navIcons2 }) : /* @__PURE__ */ jsx(AppTile, { route: icon.route, icon: navIcons2[icon.route] }),
|
|
3602
|
-
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium text-white drop-shadow-sm truncate w-full text-center", children: icon.label })
|
|
3603
|
-
]
|
|
3604
|
-
},
|
|
3605
|
-
icon.id
|
|
3606
|
-
);
|
|
3607
|
-
}) }) })
|
|
3608
|
-
] })
|
|
3609
|
-
}
|
|
3610
|
-
),
|
|
3611
|
-
draggedIcon && dragPos && /* @__PURE__ */ jsx(
|
|
3612
|
-
"div",
|
|
3613
|
-
{
|
|
3614
|
-
className: "fixed pointer-events-none z-[400] transition-none",
|
|
3615
|
-
style: {
|
|
3616
|
-
left: dragPos.x - dragOffsetRef.current.x,
|
|
3617
|
-
top: dragPos.y - dragOffsetRef.current.y,
|
|
3618
|
-
transform: "scale(1.12)"
|
|
3619
|
-
},
|
|
3620
|
-
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1 py-1 w-20", children: [
|
|
3621
|
-
draggedIcon.kind === "folder" ? /* @__PURE__ */ jsx(FolderTile, { section: draggedIcon.section, navIcons: navIcons2 }) : /* @__PURE__ */ jsx(AppTile, { route: draggedIcon.route, icon: navIcons2[draggedIcon.route] }),
|
|
3622
|
-
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium text-white drop-shadow-md truncate w-full text-center", children: draggedIcon.label })
|
|
3623
|
-
] })
|
|
3624
|
-
}
|
|
3625
|
-
),
|
|
3626
|
-
selectedFolder && /* @__PURE__ */ jsx(
|
|
3627
|
-
FolderPopup,
|
|
3628
|
-
{
|
|
3629
|
-
folder: selectedFolder,
|
|
3630
|
-
navIcons: navIcons2,
|
|
3631
|
-
onClose: () => setSelectedFolder(null),
|
|
3632
|
-
onOpenApp: (path) => {
|
|
3633
|
-
setSelectedFolder(null);
|
|
3634
|
-
onOpenApp(path);
|
|
3635
|
-
}
|
|
3636
|
-
}
|
|
3637
|
-
)
|
|
3638
|
-
] });
|
|
3639
|
-
}
|
|
3640
|
-
function FolderPopup({
|
|
3641
|
-
folder,
|
|
3642
|
-
navIcons: navIcons2,
|
|
3643
|
-
onClose,
|
|
3644
|
-
onOpenApp
|
|
3343
|
+
function MobileAppLanding({
|
|
3344
|
+
productName,
|
|
3345
|
+
productIcon,
|
|
3346
|
+
config,
|
|
3347
|
+
wallpaperStyle
|
|
3645
3348
|
}) {
|
|
3646
|
-
const
|
|
3647
|
-
const
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
};
|
|
3652
|
-
const closeThen = (after) => {
|
|
3653
|
-
if (closing) return;
|
|
3654
|
-
setClosing(true);
|
|
3655
|
-
setTimeout(after, 200);
|
|
3656
|
-
};
|
|
3657
|
-
return /* @__PURE__ */ jsxs(
|
|
3658
|
-
"div",
|
|
3659
|
-
{
|
|
3660
|
-
className: "fixed inset-0 z-[210] flex flex-col items-center justify-center px-6 bg-black/45 backdrop-blur-xl select-none",
|
|
3661
|
-
style: {
|
|
3662
|
-
paddingBottom: "calc(var(--mobile-bottom-nav, 70px) + 16px)",
|
|
3663
|
-
animation: closing ? "folder-fade-out 200ms ease-in forwards" : "folder-fade-in 220ms ease-out",
|
|
3664
|
-
WebkitUserSelect: "none",
|
|
3665
|
-
WebkitTouchCallout: "none"
|
|
3666
|
-
},
|
|
3667
|
-
onClick: beginClose,
|
|
3668
|
-
children: [
|
|
3669
|
-
/* @__PURE__ */ jsx("style", { children: `
|
|
3670
|
-
@keyframes folder-fade-in { from { opacity: 0; } to { opacity: 1; } }
|
|
3671
|
-
@keyframes folder-fade-out { from { opacity: 1; } to { opacity: 0; } }
|
|
3672
|
-
@keyframes folder-pop-in { from { opacity: 0; transform: scale(0.86) translateY(8px); } to { opacity: 1; transform: scale(1) translateY(0); } }
|
|
3673
|
-
@keyframes folder-pop-out { from { opacity: 1; transform: scale(1) translateY(0); } to { opacity: 0; transform: scale(0.9) translateY(4px); } }
|
|
3674
|
-
` }),
|
|
3675
|
-
/* @__PURE__ */ jsxs("div", { className: "w-full max-w-[304px]", children: [
|
|
3676
|
-
/* @__PURE__ */ jsx("h2", { className: "text-2xl font-semibold text-white drop-shadow-md mb-4 ml-4", children: folder.label }),
|
|
3677
|
-
/* @__PURE__ */ jsx(
|
|
3678
|
-
"div",
|
|
3679
|
-
{
|
|
3680
|
-
className: "max-h-[70vh] flex flex-col rounded-3xl bg-white/15 backdrop-blur-xl border border-white/25 shadow-2xl overflow-hidden",
|
|
3681
|
-
style: {
|
|
3682
|
-
animation: closing ? "folder-pop-out 180ms ease-in forwards" : "folder-pop-in 240ms cubic-bezier(0.34, 1.56, 0.64, 1)"
|
|
3683
|
-
},
|
|
3684
|
-
onClick: (e) => e.stopPropagation(),
|
|
3685
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto px-4 py-5", children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-4", children: folder.items.map((item) => {
|
|
3686
|
-
return /* @__PURE__ */ jsxs(
|
|
3687
|
-
"button",
|
|
3688
|
-
{
|
|
3689
|
-
onClick: () => closeThen(() => onOpenApp(item.to)),
|
|
3690
|
-
className: "flex flex-col items-center gap-1 py-1 rounded-lg active:bg-white/15",
|
|
3691
|
-
children: [
|
|
3692
|
-
/* @__PURE__ */ jsx(AppTile, { route: item.to, icon: navIcons2[item.to] }),
|
|
3693
|
-
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium text-white drop-shadow-sm truncate w-full text-center", children: item.label })
|
|
3694
|
-
]
|
|
3695
|
-
},
|
|
3696
|
-
item.to
|
|
3697
|
-
);
|
|
3698
|
-
}) }) })
|
|
3699
|
-
}
|
|
3700
|
-
)
|
|
3701
|
-
] })
|
|
3702
|
-
]
|
|
3703
|
-
}
|
|
3704
|
-
);
|
|
3705
|
-
}
|
|
3706
|
-
function MobileSwitcher({ windows, onActivate, onClose, onCloseAll }) {
|
|
3707
|
-
const [cardSize, setCardSize] = useState(() => computeCardSize());
|
|
3708
|
-
useEffect(() => {
|
|
3709
|
-
const onResize = () => setCardSize(computeCardSize());
|
|
3710
|
-
window.addEventListener("resize", onResize);
|
|
3711
|
-
return () => window.removeEventListener("resize", onResize);
|
|
3712
|
-
}, []);
|
|
3713
|
-
if (windows.length === 0) {
|
|
3714
|
-
return /* @__PURE__ */ jsxs("div", { className: "h-full flex flex-col items-center justify-center gap-3 text-white/80 px-6 text-center", children: [
|
|
3715
|
-
/* @__PURE__ */ jsxs("svg", { className: "h-12 w-12 text-white/40", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.4, children: [
|
|
3716
|
-
/* @__PURE__ */ jsx("rect", { x: "3.5", y: "3.5", width: "7", height: "7", rx: "1.25" }),
|
|
3717
|
-
/* @__PURE__ */ jsx("rect", { x: "13.5", y: "3.5", width: "7", height: "7", rx: "1.25" }),
|
|
3718
|
-
/* @__PURE__ */ jsx("rect", { x: "3.5", y: "13.5", width: "7", height: "7", rx: "1.25" }),
|
|
3719
|
-
/* @__PURE__ */ jsx("rect", { x: "13.5", y: "13.5", width: "7", height: "7", rx: "1.25" })
|
|
3720
|
-
] }),
|
|
3721
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm", children: "No open apps." }),
|
|
3722
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-white/50", children: "Tap Home to launch one." })
|
|
3723
|
-
] });
|
|
3724
|
-
}
|
|
3725
|
-
return /* @__PURE__ */ jsxs("div", { className: "h-full flex flex-col", children: [
|
|
3726
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto px-3 pt-4 pb-4", children: [
|
|
3727
|
-
/* @__PURE__ */ jsxs("h1", { className: "text-white text-base font-semibold mb-3 px-1", children: [
|
|
3728
|
-
"Open apps \xB7 ",
|
|
3729
|
-
windows.length
|
|
3730
|
-
] }),
|
|
3731
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-3", children: windows.map((w) => /* @__PURE__ */ jsxs("div", { className: "group flex flex-col items-stretch gap-1", children: [
|
|
3732
|
-
/* @__PURE__ */ jsx(
|
|
3733
|
-
ThumbCard,
|
|
3734
|
-
{
|
|
3735
|
-
id: w.id,
|
|
3736
|
-
label: w.label,
|
|
3737
|
-
maxW: cardSize.w,
|
|
3738
|
-
maxH: cardSize.h,
|
|
3739
|
-
titleAbove: true,
|
|
3740
|
-
onClick: () => onActivate(w.id),
|
|
3741
|
-
onClose: () => onClose(w.id)
|
|
3742
|
-
}
|
|
3743
|
-
),
|
|
3744
|
-
/* @__PURE__ */ jsx("span", { className: "text-[11px] text-white/80 truncate px-1", children: w.label })
|
|
3745
|
-
] }, w.id)) })
|
|
3746
|
-
] }),
|
|
3747
|
-
/* @__PURE__ */ jsx("div", { className: "shrink-0 px-3 py-3 flex justify-center", children: /* @__PURE__ */ jsx(
|
|
3748
|
-
"button",
|
|
3749
|
-
{
|
|
3750
|
-
onClick: onCloseAll,
|
|
3751
|
-
className: "px-5 py-2.5 rounded-full bg-white/15 backdrop-blur-md border border-white/25 text-white text-sm font-medium active:bg-white/25 shadow-lg",
|
|
3752
|
-
children: "Close All"
|
|
3753
|
-
}
|
|
3754
|
-
) })
|
|
3755
|
-
] });
|
|
3756
|
-
}
|
|
3757
|
-
function computeCardSize() {
|
|
3758
|
-
const w = typeof window !== "undefined" ? window.innerWidth : 360;
|
|
3759
|
-
const h = typeof window !== "undefined" ? window.innerHeight : 640;
|
|
3760
|
-
const cardW = Math.max(120, Math.floor((w - 36) / 2));
|
|
3761
|
-
const cardH = Math.min(cardW * 1.4, Math.floor(h * 0.4));
|
|
3762
|
-
return { w: cardW, h: cardH };
|
|
3763
|
-
}
|
|
3764
|
-
function timeAgo2(dateStr) {
|
|
3765
|
-
const diff = Date.now() - new Date(dateStr).getTime();
|
|
3766
|
-
const mins = Math.floor(diff / 6e4);
|
|
3767
|
-
if (mins < 1) return "just now";
|
|
3768
|
-
if (mins < 60) return `${mins}m ago`;
|
|
3769
|
-
const hrs = Math.floor(mins / 60);
|
|
3770
|
-
if (hrs < 24) return `${hrs}h ago`;
|
|
3771
|
-
const days = Math.floor(hrs / 24);
|
|
3772
|
-
if (days < 7) return `${days}d ago`;
|
|
3773
|
-
return formatDate(dateStr);
|
|
3774
|
-
}
|
|
3775
|
-
function MobileNotificationSheet({ config, onClose }) {
|
|
3776
|
-
const { list, markRead, markAllRead, onItemClick } = config;
|
|
3777
|
-
const queryClient = useQueryClient();
|
|
3778
|
-
const unreadCount = config.useUnreadCount();
|
|
3779
|
-
const { data: notifData } = useQuery({
|
|
3780
|
-
queryKey: ["notifications-dropdown"],
|
|
3781
|
-
queryFn: () => list({ page_size: 30 }),
|
|
3782
|
-
staleTime: 3e4
|
|
3783
|
-
});
|
|
3784
|
-
const notifications = notifData?.results ?? [];
|
|
3785
|
-
const handleClick = useCallback((notif) => {
|
|
3786
|
-
if (!notif.is_read) {
|
|
3787
|
-
queryClient.setQueryData(["notification-unread-count"], (old) => old ? { ...old, count: Math.max(0, (old.count || 0) - 1) } : old);
|
|
3788
|
-
queryClient.setQueryData(["notifications-dropdown"], (old) => {
|
|
3789
|
-
if (!old?.results) return old;
|
|
3790
|
-
return { ...old, results: old.results.map((n) => n.id === notif.id ? { ...n, is_read: true } : n) };
|
|
3791
|
-
});
|
|
3792
|
-
markRead(notif.id).catch(() => {
|
|
3793
|
-
queryClient.invalidateQueries({ queryKey: ["notification-unread-count"] });
|
|
3794
|
-
queryClient.invalidateQueries({ queryKey: ["notifications-dropdown"] });
|
|
3795
|
-
});
|
|
3796
|
-
}
|
|
3797
|
-
onClose();
|
|
3798
|
-
onItemClick(notif);
|
|
3799
|
-
}, [queryClient, markRead, onItemClick, onClose]);
|
|
3800
|
-
const handleMarkAllRead = () => {
|
|
3801
|
-
queryClient.setQueryData(["notification-unread-count"], (old) => old ? { ...old, count: 0 } : old);
|
|
3802
|
-
queryClient.setQueryData(["notifications-dropdown"], (old) => {
|
|
3803
|
-
if (!old?.results) return old;
|
|
3804
|
-
return { ...old, results: old.results.map((n) => ({ ...n, is_read: true })) };
|
|
3805
|
-
});
|
|
3806
|
-
markAllRead().then(() => {
|
|
3807
|
-
queryClient.invalidateQueries({ queryKey: ["notification-unread-count"] });
|
|
3808
|
-
queryClient.invalidateQueries({ queryKey: ["notifications-dropdown"] });
|
|
3809
|
-
});
|
|
3810
|
-
};
|
|
3811
|
-
return /* @__PURE__ */ jsxs(
|
|
3812
|
-
"div",
|
|
3813
|
-
{
|
|
3814
|
-
className: "fixed inset-0 z-[210] flex flex-col bg-white",
|
|
3815
|
-
style: { paddingBottom: "var(--mobile-bottom-nav, 70px)" },
|
|
3816
|
-
children: [
|
|
3817
|
-
/* @__PURE__ */ jsxs("header", { className: "flex items-center justify-between px-3 py-3 border-b border-gray-200 shrink-0", children: [
|
|
3818
|
-
/* @__PURE__ */ jsx("button", { onClick: onClose, className: "p-2 -ml-1 rounded-full active:bg-gray-200 text-gray-700", "aria-label": "Close", children: /* @__PURE__ */ jsx("svg", { className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M6 18L18 6M6 6l12 12" }) }) }),
|
|
3819
|
-
/* @__PURE__ */ jsx("h1", { className: "text-base font-semibold text-gray-900", children: "Notifications" }),
|
|
3820
|
-
unreadCount > 0 ? /* @__PURE__ */ jsx("button", { onClick: handleMarkAllRead, className: "text-xs text-blue-600 font-medium px-2 py-1 active:bg-blue-50 rounded", children: "Mark all read" }) : /* @__PURE__ */ jsx("span", { className: "w-[88px]" })
|
|
3821
|
-
] }),
|
|
3822
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 overflow-y-auto", children: notifications.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-16 px-6 text-center", children: [
|
|
3823
|
-
/* @__PURE__ */ jsx("svg", { className: "h-10 w-10 text-gray-300 mb-3", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0" }) }),
|
|
3824
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-gray-700 font-medium", children: "All caught up" }),
|
|
3825
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-400 mt-1", children: "No notifications yet" })
|
|
3826
|
-
] }) : notifications.map((notif) => /* @__PURE__ */ jsxs(
|
|
3827
|
-
"button",
|
|
3828
|
-
{
|
|
3829
|
-
onClick: () => handleClick(notif),
|
|
3830
|
-
className: "w-full flex items-start gap-3 px-4 py-3 active:bg-gray-100 border-b border-gray-100 text-left",
|
|
3831
|
-
children: [
|
|
3832
|
-
/* @__PURE__ */ jsx("div", { className: "pt-1 shrink-0", children: !notif.is_read ? /* @__PURE__ */ jsx("div", { className: "h-2.5 w-2.5 rounded-full bg-blue-500" }) : /* @__PURE__ */ jsx("div", { className: "h-2.5 w-2.5" }) }),
|
|
3833
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
3834
|
-
/* @__PURE__ */ jsx("p", { className: `text-sm leading-snug ${!notif.is_read ? "font-medium text-gray-900" : "text-gray-700"}`, children: notif.title }),
|
|
3835
|
-
notif.message && /* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mt-1 line-clamp-2", children: notif.message }),
|
|
3836
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 mt-1.5", children: [
|
|
3837
|
-
/* @__PURE__ */ jsx("span", { className: "text-[11px] text-gray-400", children: timeAgo2(notif.created_at) }),
|
|
3838
|
-
notif.actor_name && /* @__PURE__ */ jsxs("span", { className: "text-[11px] text-gray-400", children: [
|
|
3839
|
-
"by ",
|
|
3840
|
-
notif.actor_name
|
|
3841
|
-
] })
|
|
3842
|
-
] })
|
|
3843
|
-
] })
|
|
3844
|
-
]
|
|
3845
|
-
},
|
|
3846
|
-
notif.id
|
|
3847
|
-
)) })
|
|
3848
|
-
]
|
|
3849
|
-
}
|
|
3850
|
-
);
|
|
3851
|
-
}
|
|
3852
|
-
function MobileProfileSheet({ profile, user, onClose, onNavigate, onLogout }) {
|
|
3853
|
-
const initial = (profile?.first_name?.charAt(0) || user?.email?.charAt(0) || "?").toUpperCase();
|
|
3854
|
-
const displayName = profile?.first_name ? `${profile.first_name} ${profile.last_name || ""}`.trim() : user?.email ?? "Account";
|
|
3855
|
-
const groups = profile?.group_names ?? [];
|
|
3856
|
-
const handleNav = (path) => {
|
|
3857
|
-
onNavigate(path);
|
|
3858
|
-
onClose();
|
|
3859
|
-
};
|
|
3860
|
-
return /* @__PURE__ */ jsxs(
|
|
3349
|
+
const hasLink = !!config?.url;
|
|
3350
|
+
const heading = config?.heading ?? (hasLink ? `Continue in the ${productName} app` : `${productName} works best on desktop`);
|
|
3351
|
+
const description = config?.description ?? (hasLink ? "This experience is built for the mobile app. Open it to continue on your phone." : "Open this page on a larger screen to continue.");
|
|
3352
|
+
const ctaLabel = config?.ctaLabel ?? "Open the app";
|
|
3353
|
+
return /* @__PURE__ */ jsx(
|
|
3861
3354
|
"div",
|
|
3862
3355
|
{
|
|
3863
|
-
className: "
|
|
3864
|
-
style: { paddingBottom: "
|
|
3865
|
-
children:
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3874
|
-
/* @__PURE__ */
|
|
3875
|
-
|
|
3876
|
-
groups.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-2 flex flex-wrap justify-center gap-1.5", children: groups.map((g) => /* @__PURE__ */ jsx("span", { className: "text-[11px] px-2 py-0.5 rounded-full bg-gray-100 text-gray-700", children: g }, g)) })
|
|
3877
|
-
] }),
|
|
3878
|
-
/* @__PURE__ */ jsxs("div", { className: "py-2", children: [
|
|
3879
|
-
/* @__PURE__ */ jsxs(
|
|
3880
|
-
"button",
|
|
3881
|
-
{
|
|
3882
|
-
onClick: () => handleNav("/customization"),
|
|
3883
|
-
className: "w-full flex items-center gap-3 px-4 py-4 active:bg-gray-100 border-b border-gray-100 text-left",
|
|
3884
|
-
children: [
|
|
3885
|
-
/* @__PURE__ */ jsx("span", { className: "h-9 w-9 rounded-lg bg-gray-100 flex items-center justify-center text-gray-700 shrink-0", children: /* @__PURE__ */ jsxs("svg", { className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: [
|
|
3886
|
-
/* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z" }),
|
|
3887
|
-
/* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15 12a3 3 0 11-6 0 3 3 0 016 0z" })
|
|
3888
|
-
] }) }),
|
|
3889
|
-
/* @__PURE__ */ jsx("span", { className: "flex-1 text-sm font-medium text-gray-800", children: "Preferences" }),
|
|
3890
|
-
/* @__PURE__ */ jsx("svg", { className: "h-4 w-4 text-gray-400 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M8.25 4.5l7.5 7.5-7.5 7.5" }) })
|
|
3891
|
-
]
|
|
3892
|
-
}
|
|
3893
|
-
),
|
|
3894
|
-
/* @__PURE__ */ jsxs(
|
|
3895
|
-
"button",
|
|
3356
|
+
className: "flex-1 flex items-center justify-center p-6",
|
|
3357
|
+
style: { ...wallpaperStyle, paddingBottom: "calc(env(safe-area-inset-bottom) + 1.5rem)" },
|
|
3358
|
+
children: /* @__PURE__ */ jsxs(
|
|
3359
|
+
"div",
|
|
3360
|
+
{
|
|
3361
|
+
className: "w-full max-w-sm rounded-3xl p-8 flex flex-col items-center text-center",
|
|
3362
|
+
style: glassStyle(),
|
|
3363
|
+
children: [
|
|
3364
|
+
/* @__PURE__ */ jsx("div", { className: "h-20 w-20 rounded-2xl overflow-hidden bg-white/60 flex items-center justify-center shadow-sm mb-5", children: /* @__PURE__ */ jsx("img", { src: productIcon, alt: "", className: "h-full w-full object-contain p-3" }) }),
|
|
3365
|
+
/* @__PURE__ */ jsx("h1", { className: "text-xl font-semibold text-gray-900 leading-snug", children: heading }),
|
|
3366
|
+
/* @__PURE__ */ jsx("p", { className: "mt-2 text-sm text-gray-600 leading-relaxed", children: description }),
|
|
3367
|
+
hasLink && /* @__PURE__ */ jsxs(
|
|
3368
|
+
"a",
|
|
3896
3369
|
{
|
|
3897
|
-
|
|
3898
|
-
|
|
3899
|
-
|
|
3900
|
-
},
|
|
3901
|
-
className: "w-full flex items-center gap-3 px-4 py-4 active:bg-red-50 text-left",
|
|
3370
|
+
href: config.url,
|
|
3371
|
+
rel: "noopener noreferrer",
|
|
3372
|
+
className: "mt-6 w-full inline-flex items-center justify-center gap-2 rounded-xl bg-blue-600 px-5 py-3 text-sm font-semibold text-white shadow-sm transition-colors hover:bg-blue-700 active:bg-blue-800",
|
|
3902
3373
|
children: [
|
|
3903
|
-
|
|
3904
|
-
/* @__PURE__ */ jsx("
|
|
3374
|
+
ctaLabel,
|
|
3375
|
+
/* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M13.5 4.5L21 12m0 0l-7.5 7.5M21 12H3" }) })
|
|
3905
3376
|
]
|
|
3906
3377
|
}
|
|
3907
3378
|
)
|
|
3908
|
-
]
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
}
|
|
3912
|
-
);
|
|
3913
|
-
}
|
|
3914
|
-
function MobileShell({
|
|
3915
|
-
navSections: navSections2,
|
|
3916
|
-
navIcons: navIcons2,
|
|
3917
|
-
sectionIcons: sectionIcons2,
|
|
3918
|
-
wallpaperStyle,
|
|
3919
|
-
notifications,
|
|
3920
|
-
profile,
|
|
3921
|
-
user,
|
|
3922
|
-
onNavigate,
|
|
3923
|
-
onLogout
|
|
3924
|
-
}) {
|
|
3925
|
-
const { openWindows, openPage, closeEntity } = useWindowManager();
|
|
3926
|
-
const mode = useSyncExternalStore(subscribeMobileMode, getMobileMode);
|
|
3927
|
-
const [sheet, setSheet] = useState(null);
|
|
3928
|
-
const unreadCount = notifications?.useUnreadCount() ?? 0;
|
|
3929
|
-
const switcherWindows = useMemo(() => {
|
|
3930
|
-
return openWindows.filter((w) => {
|
|
3931
|
-
if (!w.route) return true;
|
|
3932
|
-
const entry = WINDOW_REGISTRY[w.route];
|
|
3933
|
-
if (!entry || !isPageEntry(entry)) return true;
|
|
3934
|
-
return !entry.widget;
|
|
3935
|
-
});
|
|
3936
|
-
}, [openWindows]);
|
|
3937
|
-
const prevOpenCountRef = useRef(openWindows.length);
|
|
3938
|
-
useEffect(() => {
|
|
3939
|
-
if (openWindows.length === 0 && mode === "app") {
|
|
3940
|
-
setMobileMode("home");
|
|
3941
|
-
}
|
|
3942
|
-
prevOpenCountRef.current = openWindows.length;
|
|
3943
|
-
}, [openWindows.length, mode]);
|
|
3944
|
-
const activateWindowById = (windowId) => {
|
|
3945
|
-
const panel = document.querySelector(`[data-modal-panel][data-window-key="${windowId}"]`);
|
|
3946
|
-
const mid = panel?.getAttribute("data-modal-id");
|
|
3947
|
-
if (mid) activateModal(mid);
|
|
3948
|
-
};
|
|
3949
|
-
const handleOpenApp = (path) => {
|
|
3950
|
-
openPage(path);
|
|
3951
|
-
setMobileMode("app");
|
|
3952
|
-
};
|
|
3953
|
-
const handleActivateWindow = (id) => {
|
|
3954
|
-
activateWindowById(id);
|
|
3955
|
-
setMobileMode("app");
|
|
3956
|
-
};
|
|
3957
|
-
const closeSheet = () => setSheet(null);
|
|
3958
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3959
|
-
/* @__PURE__ */ jsx(
|
|
3960
|
-
"div",
|
|
3961
|
-
{
|
|
3962
|
-
className: "fixed inset-0 z-0 pointer-events-none",
|
|
3963
|
-
style: wallpaperStyle
|
|
3964
|
-
}
|
|
3965
|
-
),
|
|
3966
|
-
mode === "home" && /* @__PURE__ */ jsx(
|
|
3967
|
-
"div",
|
|
3968
|
-
{
|
|
3969
|
-
className: "fixed inset-0 z-[200]",
|
|
3970
|
-
style: {
|
|
3971
|
-
...wallpaperStyle,
|
|
3972
|
-
paddingBottom: "var(--mobile-bottom-nav, 70px)"
|
|
3973
|
-
},
|
|
3974
|
-
children: /* @__PURE__ */ jsx(
|
|
3975
|
-
MobileHome,
|
|
3976
|
-
{
|
|
3977
|
-
navSections: navSections2,
|
|
3978
|
-
navIcons: navIcons2,
|
|
3979
|
-
sectionIcons: sectionIcons2,
|
|
3980
|
-
openWindows,
|
|
3981
|
-
onOpenApp: handleOpenApp,
|
|
3982
|
-
onActivateWindow: handleActivateWindow
|
|
3983
|
-
}
|
|
3984
|
-
)
|
|
3985
|
-
}
|
|
3986
|
-
),
|
|
3987
|
-
mode === "switcher" && /* @__PURE__ */ jsx("div", { className: "fixed inset-0 z-[200] bg-gray-900/95 backdrop-blur-sm", style: { paddingBottom: "var(--mobile-bottom-nav, 70px)" }, children: /* @__PURE__ */ jsx(
|
|
3988
|
-
MobileSwitcher,
|
|
3989
|
-
{
|
|
3990
|
-
windows: switcherWindows,
|
|
3991
|
-
onActivate: handleActivateWindow,
|
|
3992
|
-
onClose: (id) => closeEntity(id),
|
|
3993
|
-
onCloseAll: () => switcherWindows.forEach((w) => closeEntity(w.id))
|
|
3994
|
-
}
|
|
3995
|
-
) }),
|
|
3996
|
-
sheet === "notifications" && notifications && /* @__PURE__ */ jsx(MobileNotificationSheet, { config: notifications, onClose: closeSheet }),
|
|
3997
|
-
sheet === "profile" && /* @__PURE__ */ jsx(
|
|
3998
|
-
MobileProfileSheet,
|
|
3999
|
-
{
|
|
4000
|
-
profile,
|
|
4001
|
-
user,
|
|
4002
|
-
onClose: closeSheet,
|
|
4003
|
-
onNavigate: (path) => {
|
|
4004
|
-
onNavigate?.(path);
|
|
4005
|
-
},
|
|
4006
|
-
onLogout: () => onLogout?.()
|
|
4007
|
-
}
|
|
4008
|
-
),
|
|
4009
|
-
/* @__PURE__ */ jsx(
|
|
4010
|
-
MobileBottomNav,
|
|
4011
|
-
{
|
|
4012
|
-
mode,
|
|
4013
|
-
unreadCount,
|
|
4014
|
-
showNotifications: !!notifications,
|
|
4015
|
-
profileAvatar: profile?.avatar_url,
|
|
4016
|
-
profileInitial: (profile?.first_name?.charAt(0) || user?.email?.charAt(0) || "?").toUpperCase(),
|
|
4017
|
-
onHome: () => {
|
|
4018
|
-
closeSheet();
|
|
4019
|
-
setMobileMode("home");
|
|
4020
|
-
},
|
|
4021
|
-
onSwitcher: () => {
|
|
4022
|
-
closeSheet();
|
|
4023
|
-
setMobileMode("switcher");
|
|
4024
|
-
},
|
|
4025
|
-
onNotifications: () => setSheet(sheet === "notifications" ? null : "notifications"),
|
|
4026
|
-
onProfile: () => setSheet(sheet === "profile" ? null : "profile")
|
|
4027
|
-
}
|
|
4028
|
-
)
|
|
4029
|
-
] });
|
|
4030
|
-
}
|
|
4031
|
-
function MobileBottomNav({
|
|
4032
|
-
mode,
|
|
4033
|
-
unreadCount,
|
|
4034
|
-
showNotifications,
|
|
4035
|
-
profileAvatar,
|
|
4036
|
-
profileInitial,
|
|
4037
|
-
onHome,
|
|
4038
|
-
onSwitcher,
|
|
4039
|
-
onNotifications,
|
|
4040
|
-
onProfile
|
|
4041
|
-
}) {
|
|
4042
|
-
const btnClass = (active) => `flex-1 flex flex-col items-center justify-center gap-0.5 py-2 transition-colors select-none ${active ? "text-blue-600" : "text-gray-700 active:text-gray-900"}`;
|
|
4043
|
-
return /* @__PURE__ */ jsxs(
|
|
4044
|
-
"nav",
|
|
4045
|
-
{
|
|
4046
|
-
className: "fixed bottom-0 inset-x-0 z-[300] flex items-stretch border-t border-white/40",
|
|
4047
|
-
style: {
|
|
4048
|
-
height: "var(--mobile-bottom-nav, 70px)",
|
|
4049
|
-
paddingBottom: "env(safe-area-inset-bottom)",
|
|
4050
|
-
WebkitBackdropFilter: "blur(28px) saturate(1.8)",
|
|
4051
|
-
backdropFilter: "blur(28px) saturate(1.8)",
|
|
4052
|
-
background: "linear-gradient(135deg, rgba(255,255,255,0.65) 0%, rgba(255,255,255,0.45) 50%, rgba(255,255,255,0.55) 100%)",
|
|
4053
|
-
boxShadow: "inset 0 1px 0 rgba(255,255,255,0.6), 0 -2px 12px rgba(0,0,0,0.08)"
|
|
4054
|
-
},
|
|
4055
|
-
children: [
|
|
4056
|
-
/* @__PURE__ */ jsxs("button", { onClick: onHome, className: btnClass(mode === "home"), "aria-label": "Home", children: [
|
|
4057
|
-
/* @__PURE__ */ jsx("svg", { className: "h-8 w-8", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.7, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M2.25 12l8.954-8.955c.44-.439 1.152-.439 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25" }) }),
|
|
4058
|
-
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium", children: "Home" })
|
|
4059
|
-
] }),
|
|
4060
|
-
/* @__PURE__ */ jsxs("button", { onClick: onSwitcher, className: btnClass(mode === "switcher"), "aria-label": "App switcher", children: [
|
|
4061
|
-
/* @__PURE__ */ jsxs("svg", { className: "h-8 w-8", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.7, children: [
|
|
4062
|
-
/* @__PURE__ */ jsx("rect", { x: "3.5", y: "3.5", width: "7", height: "7", rx: "1.25" }),
|
|
4063
|
-
/* @__PURE__ */ jsx("rect", { x: "13.5", y: "3.5", width: "7", height: "7", rx: "1.25" }),
|
|
4064
|
-
/* @__PURE__ */ jsx("rect", { x: "3.5", y: "13.5", width: "7", height: "7", rx: "1.25" }),
|
|
4065
|
-
/* @__PURE__ */ jsx("rect", { x: "13.5", y: "13.5", width: "7", height: "7", rx: "1.25" })
|
|
4066
|
-
] }),
|
|
4067
|
-
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium", children: "Apps" })
|
|
4068
|
-
] }),
|
|
4069
|
-
showNotifications && /* @__PURE__ */ jsxs("button", { onClick: onNotifications, className: btnClass(false), "aria-label": "Notifications", children: [
|
|
4070
|
-
/* @__PURE__ */ jsxs("span", { className: "relative", children: [
|
|
4071
|
-
/* @__PURE__ */ jsx("svg", { className: "h-8 w-8", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.7, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0" }) }),
|
|
4072
|
-
unreadCount > 0 && /* @__PURE__ */ jsx("span", { className: "absolute -top-1.5 -right-2 min-w-[18px] h-[18px] px-1 rounded-full bg-red-500 text-white text-[10px] font-bold leading-[18px] text-center", children: unreadCount > 99 ? "99+" : unreadCount })
|
|
4073
|
-
] }),
|
|
4074
|
-
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium", children: "Alerts" })
|
|
4075
|
-
] }),
|
|
4076
|
-
/* @__PURE__ */ jsxs("button", { onClick: onProfile, className: btnClass(false), "aria-label": "Profile", children: [
|
|
4077
|
-
profileAvatar ? /* @__PURE__ */ jsx("img", { src: profileAvatar, alt: "", className: "h-8 w-8 rounded-full object-cover border border-gray-200" }) : /* @__PURE__ */ jsx("div", { className: "h-8 w-8 rounded-full bg-blue-100 flex items-center justify-center text-xs font-bold text-blue-700", children: profileInitial }),
|
|
4078
|
-
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium", children: "Profile" })
|
|
4079
|
-
] })
|
|
4080
|
-
]
|
|
3379
|
+
]
|
|
3380
|
+
}
|
|
3381
|
+
)
|
|
4081
3382
|
}
|
|
4082
3383
|
);
|
|
4083
3384
|
}
|
|
@@ -4361,7 +3662,8 @@ function Layout({
|
|
|
4361
3662
|
notifications,
|
|
4362
3663
|
search,
|
|
4363
3664
|
taskbarTrayLeft,
|
|
4364
|
-
clockCalendar
|
|
3665
|
+
clockCalendar,
|
|
3666
|
+
mobileApp
|
|
4365
3667
|
} = {}) {
|
|
4366
3668
|
const host = useDesktopHost();
|
|
4367
3669
|
const { user, logout, hasAnyPerm } = useAuth();
|
|
@@ -4423,8 +3725,8 @@ function Layout({
|
|
|
4423
3725
|
root.style.setProperty("--window-tab-font-size", sv.tabFont);
|
|
4424
3726
|
}, [reduceTransparency, inactiveHeaderOpacity, inactiveContentOpacity, activeHeaderOpacity, activeContentOpacity, taskbarH, taskbarPosition, prefs.default_window_size, prefs.window_position, prefs.menu_density, prefs.start_menu_size, sidebarWidth, layoutMode]);
|
|
4425
3727
|
useEffect(() => {
|
|
4426
|
-
document.documentElement.style.setProperty("--mobile-bottom-nav",
|
|
4427
|
-
}, [
|
|
3728
|
+
document.documentElement.style.setProperty("--mobile-bottom-nav", "0px");
|
|
3729
|
+
}, []);
|
|
4428
3730
|
const [balloonDismissed, setBalloonDismissed] = useState(false);
|
|
4429
3731
|
const [isFullscreen, setIsFullscreen] = useState(!!document.fullscreenElement);
|
|
4430
3732
|
const [taskbarMenu, setTaskbarMenu] = useState(null);
|
|
@@ -4582,19 +3884,12 @@ function Layout({
|
|
|
4582
3884
|
};
|
|
4583
3885
|
if (isMobile) {
|
|
4584
3886
|
return /* @__PURE__ */ jsx(
|
|
4585
|
-
|
|
3887
|
+
MobileAppLanding,
|
|
4586
3888
|
{
|
|
4587
3889
|
productName,
|
|
4588
3890
|
productIcon,
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
sectionIcons: sectionIcons2,
|
|
4592
|
-
wallpaperStyle,
|
|
4593
|
-
notifications,
|
|
4594
|
-
profile,
|
|
4595
|
-
user,
|
|
4596
|
-
onNavigate: (path) => openPage(path),
|
|
4597
|
-
onLogout: () => setShowLogout(true)
|
|
3891
|
+
config: mobileApp,
|
|
3892
|
+
wallpaperStyle
|
|
4598
3893
|
}
|
|
4599
3894
|
);
|
|
4600
3895
|
}
|
|
@@ -8964,7 +8259,7 @@ function ContainerFillChart({
|
|
|
8964
8259
|
}
|
|
8965
8260
|
var DEFAULT_POLL_MS = 15e3;
|
|
8966
8261
|
var DEFAULT_REQUEST_TIMEOUT_MS = 5e3;
|
|
8967
|
-
function
|
|
8262
|
+
function timeAgo2(date) {
|
|
8968
8263
|
if (!date) return "\u2014";
|
|
8969
8264
|
const diff = Math.max(0, Date.now() - date.getTime());
|
|
8970
8265
|
if (diff < 1500) return "just now";
|
|
@@ -9153,12 +8448,12 @@ function ServerStatusIndicator({
|
|
|
9153
8448
|
/* @__PURE__ */ jsxs("p", { className: "mt-1 text-[11px] text-gray-500", children: [
|
|
9154
8449
|
status === "connected" && lastOkAt && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9155
8450
|
"Last poll ",
|
|
9156
|
-
|
|
8451
|
+
timeAgo2(lastOkAt),
|
|
9157
8452
|
"."
|
|
9158
8453
|
] }),
|
|
9159
8454
|
status === "disconnected" && lastFailAt && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9160
8455
|
"Last failure ",
|
|
9161
|
-
|
|
8456
|
+
timeAgo2(lastFailAt),
|
|
9162
8457
|
"."
|
|
9163
8458
|
] }),
|
|
9164
8459
|
status === "checking" && /* @__PURE__ */ jsx(Fragment, { children: "First poll in flight\u2026" })
|
|
@@ -9176,7 +8471,7 @@ function ServerStatusIndicator({
|
|
|
9176
8471
|
/* @__PURE__ */ jsx("span", { className: "tabular-nums", children: lastOkAt.toLocaleTimeString() }),
|
|
9177
8472
|
/* @__PURE__ */ jsxs("span", { className: "text-gray-400 ml-1", children: [
|
|
9178
8473
|
"\xB7 ",
|
|
9179
|
-
|
|
8474
|
+
timeAgo2(lastOkAt)
|
|
9180
8475
|
] })
|
|
9181
8476
|
] }) : "\u2014" }),
|
|
9182
8477
|
lastFailAt && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -9185,7 +8480,7 @@ function ServerStatusIndicator({
|
|
|
9185
8480
|
/* @__PURE__ */ jsx("span", { className: "tabular-nums", children: lastFailAt.toLocaleTimeString() }),
|
|
9186
8481
|
/* @__PURE__ */ jsxs("span", { className: "text-gray-400 ml-1", children: [
|
|
9187
8482
|
"\xB7 ",
|
|
9188
|
-
|
|
8483
|
+
timeAgo2(lastFailAt)
|
|
9189
8484
|
] })
|
|
9190
8485
|
] })
|
|
9191
8486
|
] }),
|