react-os-shell 0.2.1 → 0.2.18
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-EBBYHPBS.js} +3 -3
- package/dist/{Browser-IAQ5N3LL.js.map → Browser-EBBYHPBS.js.map} +1 -1
- package/dist/{Calculator-7MIONNJK.js → Calculator-CAKKD24W.js} +4 -4
- package/dist/{Calculator-7MIONNJK.js.map → Calculator-CAKKD24W.js.map} +1 -1
- package/dist/{Calendar-2R2DWXTG.js → Calendar-DHAUIE7N.js} +3 -3
- package/dist/{Calendar-2R2DWXTG.js.map → Calendar-DHAUIE7N.js.map} +1 -1
- package/dist/{CurrencyConverter-BMTB7FLA.js → CurrencyConverter-5LWH5WLH.js} +4 -4
- package/dist/{CurrencyConverter-BMTB7FLA.js.map → CurrencyConverter-5LWH5WLH.js.map} +1 -1
- package/dist/{Documents-CBNJAM3Q.js → Documents-LECUPQZ4.js} +3 -3
- package/dist/{Documents-CBNJAM3Q.js.map → Documents-LECUPQZ4.js.map} +1 -1
- package/dist/{Email-BS6MESSZ.js → Email-AJYKU4M7.js} +3 -3
- package/dist/{Email-BS6MESSZ.js.map → Email-AJYKU4M7.js.map} +1 -1
- package/dist/Files-RPYWW7CV.js +7 -0
- package/dist/{Files-U3BSTCC3.js.map → Files-RPYWW7CV.js.map} +1 -1
- package/dist/{Minesweeper-XOSH6BW2.js → Minesweeper-JKDGSZMW.js} +3 -3
- package/dist/{Minesweeper-XOSH6BW2.js.map → Minesweeper-JKDGSZMW.js.map} +1 -1
- package/dist/{Notepad-DMSBGGMS.js → Notepad-VL2E3ZAM.js} +3 -3
- package/dist/{Notepad-DMSBGGMS.js.map → Notepad-VL2E3ZAM.js.map} +1 -1
- package/dist/{PomodoroTimer-3XLLIDV3.js → PomodoroTimer-5WFFVIXI.js} +4 -4
- package/dist/{PomodoroTimer-3XLLIDV3.js.map → PomodoroTimer-5WFFVIXI.js.map} +1 -1
- package/dist/Preview-WE6TMZ2L.js +6 -0
- package/dist/{Preview-Y2LMO2DL.js.map → Preview-WE6TMZ2L.js.map} +1 -1
- package/dist/{Spreadsheet-IRPGCABR.js → Spreadsheet-COXQUNF6.js} +3 -3
- package/dist/{Spreadsheet-IRPGCABR.js.map → Spreadsheet-COXQUNF6.js.map} +1 -1
- package/dist/{Weather-5IW43PAQ.js → Weather-4ZPRC6CB.js} +4 -4
- package/dist/{Weather-5IW43PAQ.js.map → Weather-4ZPRC6CB.js.map} +1 -1
- package/dist/apps/index.js +16 -16
- package/dist/{chunk-DIJ46HNS.js → chunk-CXR7YLO7.js} +3 -3
- package/dist/{chunk-DIJ46HNS.js.map → chunk-CXR7YLO7.js.map} +1 -1
- package/dist/{chunk-JEJHECSO.js → chunk-HTNCG36G.js} +4 -4
- package/dist/{chunk-JEJHECSO.js.map → chunk-HTNCG36G.js.map} +1 -1
- package/dist/{chunk-7P6DO3NC.js → chunk-IDUZR4KY.js} +27 -12
- package/dist/chunk-IDUZR4KY.js.map +1 -0
- package/dist/{chunk-IQV6QQBQ.js → chunk-QF5IZXIA.js} +3 -3
- package/dist/{chunk-IQV6QQBQ.js.map → chunk-QF5IZXIA.js.map} +1 -1
- package/dist/index.d.ts +9 -2
- package/dist/index.js +206 -197
- 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
package/dist/index.d.ts
CHANGED
|
@@ -633,6 +633,11 @@ declare function useShellEntityFetcher(): EntityFetcher;
|
|
|
633
633
|
* Outside calls (anything not hitting `/auth/me/`) need the consumer to mount
|
|
634
634
|
* <ShellEntityFetcherProvider> and wire `entityFetcher` on <WindowManager>.
|
|
635
635
|
*
|
|
636
|
+
* When `setShellApiClient` has not been called, HTTP methods resolve with an
|
|
637
|
+
* empty payload instead of throwing — so consumers without a backend (the
|
|
638
|
+
* Pages demo, for instance) can still mount the shell. A one-time console
|
|
639
|
+
* warning surfaces the missing wiring without crashing the app.
|
|
640
|
+
*
|
|
636
641
|
* Long-term this file is removed when each call site migrates to
|
|
637
642
|
* `useShellPrefs()` directly.
|
|
638
643
|
*/
|
|
@@ -659,8 +664,10 @@ declare function setShellAuthBridge(bridge: {
|
|
|
659
664
|
declare function glassStyle(opacity?: number): CSSProperties;
|
|
660
665
|
/** Glass divider border color */
|
|
661
666
|
declare const GLASS_DIVIDER = "border-white/20";
|
|
662
|
-
/** Glass input/search bar background
|
|
663
|
-
|
|
667
|
+
/** Glass input/search bar background — declared in styles.css so it can adapt
|
|
668
|
+
* to dark mode (a flat `bg-white/15` reads as a too-bright tile on the dark
|
|
669
|
+
* glass gradient). */
|
|
670
|
+
declare const GLASS_INPUT_BG = "glass-input-bg";
|
|
664
671
|
|
|
665
672
|
declare function reportBug(submit: BugReportConfig['submit']): Promise<void>;
|
|
666
673
|
|
package/dist/index.js
CHANGED
|
@@ -5,11 +5,11 @@ import { useGoogleAuth } from './chunk-46LICZUM.js';
|
|
|
5
5
|
import { useShellPrefs } from './chunk-36VM54SC.js';
|
|
6
6
|
export { ShellPrefsProvider, useLocalStoragePrefs, useShellPrefs } from './chunk-36VM54SC.js';
|
|
7
7
|
import { playNotification, playStartup, soundsEnabled, getSoundConfig, SOUND_PACK_KEYS, SOUND_PACKS, SOUND_TYPES, SOUND_TYPE_LABELS, playLogout, setSoundForType, previewSound, setAllSounds } from './chunk-D7PYW2QS.js';
|
|
8
|
-
import { setPdfPreview } from './chunk-
|
|
8
|
+
import { setPdfPreview } from './chunk-QF5IZXIA.js';
|
|
9
9
|
import { toast_default } from './chunk-WIJ45SYD.js';
|
|
10
10
|
export { toast_default as toast } from './chunk-WIJ45SYD.js';
|
|
11
|
-
import { useWindowManager, glassStyle, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, startMenuCategories, useIsMobile, navSections, isSection, GLASS_INPUT_BG, navIcons, sectionIcons, ModalActions, useModalActive, subscribeMobileMode, getMobileMode,
|
|
12
|
-
export { CancelButton, CopyButton, DocFavStar, GLASS_DIVIDER, GLASS_INPUT_BG, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, WindowManagerProvider, WindowTitle, glassStyle, isEntityEntry, isPageEntry, setShellApiClient, setShellNavIcons, setShellWindowRegistry, useModalActive, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-
|
|
11
|
+
import { useWindowManager, glassStyle, PopupMenu, PopupMenuLabel, PopupMenuDivider, PopupMenuItem, Modal, startMenuCategories, useIsMobile, navSections, isSection, GLASS_INPUT_BG, navIcons, sectionIcons, ModalActions, useModalActive, subscribeMobileMode, getMobileMode, WINDOW_REGISTRY, isPageEntry, setMobileMode, LoadingSpinner, ThumbCard, activateModal } from './chunk-IDUZR4KY.js';
|
|
12
|
+
export { CancelButton, CopyButton, DocFavStar, GLASS_DIVIDER, GLASS_INPUT_BG, Modal, ModalActions, PopupMenu, PopupMenuDivider, PopupMenuItem, PopupMenuLabel, WindowManagerProvider, WindowTitle, glassStyle, isEntityEntry, isPageEntry, setShellApiClient, setShellNavIcons, setShellWindowRegistry, useModalActive, useWidgetSettings, useWindowManager, useWindowMenuItem, useWindowTitle } from './chunk-IDUZR4KY.js';
|
|
13
13
|
export { ConfirmProvider, confirm, confirmDestructive, prompt } from './chunk-PLGHQ7QW.js';
|
|
14
14
|
import { createContext, useState, useRef, useEffect, useCallback, useLayoutEffect, useContext, isValidElement, cloneElement, useSyncExternalStore, useMemo, Suspense } from 'react';
|
|
15
15
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
@@ -706,7 +706,7 @@ function StatusBadge({ status }) {
|
|
|
706
706
|
}
|
|
707
707
|
|
|
708
708
|
// src/version.ts
|
|
709
|
-
var VERSION = "0.2.
|
|
709
|
+
var VERSION = "0.2.17" ;
|
|
710
710
|
var APP_VERSION = VERSION;
|
|
711
711
|
|
|
712
712
|
// src/changelog.ts
|
|
@@ -2794,6 +2794,28 @@ function StartMenu({
|
|
|
2794
2794
|
var MOBILE_WIDGET_ORDER_KEY = "erp_mobile_widget_order";
|
|
2795
2795
|
var MOBILE_HOME_ORDER_KEY = "erp_mobile_home_order";
|
|
2796
2796
|
var LONG_PRESS_MS = 400;
|
|
2797
|
+
var ICON_GRADIENTS = [
|
|
2798
|
+
"from-blue-500 to-blue-700",
|
|
2799
|
+
"from-indigo-500 to-purple-600",
|
|
2800
|
+
"from-purple-500 to-pink-600",
|
|
2801
|
+
"from-pink-500 to-rose-600",
|
|
2802
|
+
"from-red-500 to-rose-600",
|
|
2803
|
+
"from-orange-500 to-red-600",
|
|
2804
|
+
"from-amber-500 to-orange-600",
|
|
2805
|
+
"from-yellow-500 to-amber-500",
|
|
2806
|
+
"from-lime-500 to-green-600",
|
|
2807
|
+
"from-green-500 to-emerald-600",
|
|
2808
|
+
"from-emerald-500 to-teal-600",
|
|
2809
|
+
"from-teal-500 to-cyan-600",
|
|
2810
|
+
"from-cyan-500 to-sky-600",
|
|
2811
|
+
"from-sky-500 to-blue-600",
|
|
2812
|
+
"from-violet-500 to-fuchsia-600"
|
|
2813
|
+
];
|
|
2814
|
+
function hashGradient(seed) {
|
|
2815
|
+
let h = 0;
|
|
2816
|
+
for (let i = 0; i < seed.length; i++) h = (h << 5) - h + seed.charCodeAt(i);
|
|
2817
|
+
return ICON_GRADIENTS[Math.abs(h) % ICON_GRADIENTS.length];
|
|
2818
|
+
}
|
|
2797
2819
|
function loadOrder(key) {
|
|
2798
2820
|
try {
|
|
2799
2821
|
const raw = localStorage.getItem(key);
|
|
@@ -2811,7 +2833,6 @@ function saveOrder(key, order) {
|
|
|
2811
2833
|
} catch {
|
|
2812
2834
|
}
|
|
2813
2835
|
}
|
|
2814
|
-
var FALLBACK_FOLDER_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 9.776c.112-.017.227-.026.344-.026h15.812c.117 0 .232.009.344.026m-16.5 0a2.25 2.25 0 00-1.883 2.542l.857 6a2.25 2.25 0 002.227 1.932H19.05a2.25 2.25 0 002.227-1.932l.857-6a2.25 2.25 0 00-1.883-2.542m-16.5 0V6A2.25 2.25 0 016 3.75h3.879a1.5 1.5 0 011.06.44l2.122 2.12a1.5 1.5 0 001.06.44H18A2.25 2.25 0 0120.25 9v.776" }) });
|
|
2815
2836
|
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" }) });
|
|
2816
2837
|
function sizeIcon(node, fallback, sizeClass = "h-10 w-10") {
|
|
2817
2838
|
if (!node) return fallback;
|
|
@@ -2822,6 +2843,23 @@ function sizeIcon(node, fallback, sizeClass = "h-10 w-10") {
|
|
|
2822
2843
|
}
|
|
2823
2844
|
return node;
|
|
2824
2845
|
}
|
|
2846
|
+
function AppTile({ route, icon }) {
|
|
2847
|
+
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") });
|
|
2848
|
+
}
|
|
2849
|
+
function FolderTile({ section, navIcons: navIcons2 }) {
|
|
2850
|
+
const previewItems = section.items.slice(0, 4);
|
|
2851
|
+
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: [
|
|
2852
|
+
previewItems.map((item) => /* @__PURE__ */ jsx(
|
|
2853
|
+
"span",
|
|
2854
|
+
{
|
|
2855
|
+
className: `rounded-md bg-gradient-to-br ${hashGradient(item.to)} flex items-center justify-center text-white`,
|
|
2856
|
+
children: sizeIcon(navIcons2[item.to], FALLBACK_APP_ICON, "h-3.5 w-3.5")
|
|
2857
|
+
},
|
|
2858
|
+
item.to
|
|
2859
|
+
)),
|
|
2860
|
+
Array.from({ length: Math.max(0, 4 - previewItems.length) }).map((_, i) => /* @__PURE__ */ jsx("span", { className: "rounded-md bg-white/20" }, `empty-${i}`))
|
|
2861
|
+
] });
|
|
2862
|
+
}
|
|
2825
2863
|
function MobileHome({
|
|
2826
2864
|
navSections: navSections2,
|
|
2827
2865
|
navIcons: navIcons2,
|
|
@@ -2943,7 +2981,7 @@ function MobileHome({
|
|
|
2943
2981
|
if (icon.kind === "app") onOpenApp(icon.route);
|
|
2944
2982
|
else setSelectedFolder(icon.section);
|
|
2945
2983
|
};
|
|
2946
|
-
const [widgetOrder,
|
|
2984
|
+
const [widgetOrder, _setWidgetOrder] = useState(() => loadOrder(MOBILE_WIDGET_ORDER_KEY));
|
|
2947
2985
|
const widgetWindows = useMemo(() => {
|
|
2948
2986
|
const widgets = openWindows.filter((w) => {
|
|
2949
2987
|
if (!w.route) return false;
|
|
@@ -2963,23 +3001,11 @@ function MobileHome({
|
|
|
2963
3001
|
...visibleRoutes.filter((r) => !widgetOrder.includes(r))
|
|
2964
3002
|
];
|
|
2965
3003
|
if (next.length !== widgetOrder.length || next.some((r, i) => r !== widgetOrder[i])) {
|
|
2966
|
-
|
|
3004
|
+
_setWidgetOrder(next);
|
|
2967
3005
|
saveOrder(MOBILE_WIDGET_ORDER_KEY, next);
|
|
2968
3006
|
}
|
|
2969
3007
|
}, [widgetWindows, widgetOrder]);
|
|
2970
|
-
|
|
2971
|
-
setWidgetOrder((prev) => {
|
|
2972
|
-
const i = prev.indexOf(route);
|
|
2973
|
-
if (i === -1) return prev;
|
|
2974
|
-
const j = i + dir;
|
|
2975
|
-
if (j < 0 || j >= prev.length) return prev;
|
|
2976
|
-
const next = prev.slice();
|
|
2977
|
-
[next[i], next[j]] = [next[j], next[i]];
|
|
2978
|
-
saveOrder(MOBILE_WIDGET_ORDER_KEY, next);
|
|
2979
|
-
return next;
|
|
2980
|
-
});
|
|
2981
|
-
};
|
|
2982
|
-
const openCountByRoute = useMemo(() => {
|
|
3008
|
+
useMemo(() => {
|
|
2983
3009
|
const map = /* @__PURE__ */ new Map();
|
|
2984
3010
|
for (const w of openWindows) {
|
|
2985
3011
|
if (!w.route) continue;
|
|
@@ -2987,85 +3013,56 @@ function MobileHome({
|
|
|
2987
3013
|
}
|
|
2988
3014
|
return map;
|
|
2989
3015
|
}, [openWindows]);
|
|
2990
|
-
const openInFolder = (folder) => {
|
|
2991
|
-
const routes = new Set(folder.items.map((i) => i.to));
|
|
2992
|
-
return openWindows.filter((w) => w.route && routes.has(w.route));
|
|
2993
|
-
};
|
|
2994
3016
|
const draggedIcon = dragId ? homeIcons.find((i) => i.id === dragId) : null;
|
|
2995
3017
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2996
|
-
/* @__PURE__ */
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3016
|
-
|
|
3017
|
-
|
|
3018
|
-
|
|
3019
|
-
|
|
3020
|
-
|
|
3021
|
-
|
|
3022
|
-
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
onPointerDown: (e) => beginLongPress(icon.id, e),
|
|
3045
|
-
onPointerUp: cancelLongPress,
|
|
3046
|
-
onPointerCancel: cancelLongPress,
|
|
3047
|
-
onPointerLeave: cancelLongPress,
|
|
3048
|
-
onClick: () => handleIconClick(icon),
|
|
3049
|
-
style: { touchAction: "none", visibility: isBeingDragged ? "hidden" : "visible" },
|
|
3050
|
-
className: `flex flex-col items-center gap-1 py-1 rounded-lg active:bg-white/40 ${dragId && !isBeingDragged ? "transition-transform" : ""}`,
|
|
3051
|
-
children: [
|
|
3052
|
-
/* @__PURE__ */ jsxs(
|
|
3053
|
-
"span",
|
|
3054
|
-
{
|
|
3055
|
-
className: `relative h-[72px] w-[72px] rounded-2xl flex items-center justify-center shadow-sm border ${isFolder ? "bg-white/70 backdrop-blur border-white/40 text-blue-700" : "bg-white/85 backdrop-blur border-white/40 text-gray-800"}`,
|
|
3056
|
-
children: [
|
|
3057
|
-
isFolder ? sizeIcon(sectionIcons2[icon.label], FALLBACK_FOLDER_ICON) : sizeIcon(navIcons2[icon.route], FALLBACK_APP_ICON),
|
|
3058
|
-
openCount > 0 && (isFolder ? /* @__PURE__ */ jsx("span", { className: "absolute -top-1 -right-1 min-w-[18px] h-[18px] px-1 rounded-full bg-blue-500 text-white text-[10px] font-bold leading-[18px] text-center border-2 border-white", children: openCount }) : /* @__PURE__ */ jsx("span", { className: "absolute -top-1 -right-1 h-2 w-2 rounded-full bg-blue-500 border-2 border-white" }))
|
|
3059
|
-
]
|
|
3060
|
-
}
|
|
3061
|
-
),
|
|
3062
|
-
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium text-white drop-shadow-sm truncate w-full text-center", children: icon.label })
|
|
3063
|
-
]
|
|
3064
|
-
},
|
|
3065
|
-
icon.id
|
|
3066
|
-
);
|
|
3067
|
-
}) }) })
|
|
3068
|
-
] }),
|
|
3018
|
+
/* @__PURE__ */ jsx(
|
|
3019
|
+
"div",
|
|
3020
|
+
{
|
|
3021
|
+
className: "h-full overflow-y-auto px-4 pt-4 pb-4 select-none",
|
|
3022
|
+
style: {
|
|
3023
|
+
// Disable iOS long-press text-selection / "Copy" callout on icon labels.
|
|
3024
|
+
WebkitUserSelect: "none",
|
|
3025
|
+
WebkitTouchCallout: "none"
|
|
3026
|
+
},
|
|
3027
|
+
children: /* @__PURE__ */ jsxs("div", { children: [
|
|
3028
|
+
widgetWindows.length > 0 && /* @__PURE__ */ jsx("section", { className: "mb-4", children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-4 gap-4", children: widgetWindows.map((w) => {
|
|
3029
|
+
const entry = WINDOW_REGISTRY[w.route];
|
|
3030
|
+
if (!entry) return null;
|
|
3031
|
+
const Component = entry.component;
|
|
3032
|
+
return /* @__PURE__ */ jsx(
|
|
3033
|
+
"div",
|
|
3034
|
+
{
|
|
3035
|
+
className: "col-span-2 relative rounded-2xl bg-white/85 backdrop-blur border border-white/40 shadow-md overflow-hidden aspect-square",
|
|
3036
|
+
children: /* @__PURE__ */ jsx(Suspense, { fallback: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ jsx(LoadingSpinner, {}) }), children: /* @__PURE__ */ jsx(Component, {}) })
|
|
3037
|
+
},
|
|
3038
|
+
w.id
|
|
3039
|
+
);
|
|
3040
|
+
}) }) }),
|
|
3041
|
+
homeIcons.length > 0 && /* @__PURE__ */ jsx("section", { children: /* @__PURE__ */ jsx("div", { className: "grid grid-cols-4 gap-4", children: homeIcons.map((icon) => {
|
|
3042
|
+
const isFolder = icon.kind === "folder";
|
|
3043
|
+
const isBeingDragged = dragId === icon.id;
|
|
3044
|
+
return /* @__PURE__ */ jsxs(
|
|
3045
|
+
"button",
|
|
3046
|
+
{
|
|
3047
|
+
"data-home-icon-id": icon.id,
|
|
3048
|
+
onPointerDown: (e) => beginLongPress(icon.id, e),
|
|
3049
|
+
onPointerUp: cancelLongPress,
|
|
3050
|
+
onPointerCancel: cancelLongPress,
|
|
3051
|
+
onPointerLeave: cancelLongPress,
|
|
3052
|
+
onClick: () => handleIconClick(icon),
|
|
3053
|
+
style: { touchAction: "none", visibility: isBeingDragged ? "hidden" : "visible" },
|
|
3054
|
+
className: `flex flex-col items-center gap-1 py-1 rounded-lg active:bg-white/20 ${dragId && !isBeingDragged ? "transition-transform" : ""}`,
|
|
3055
|
+
children: [
|
|
3056
|
+
isFolder ? /* @__PURE__ */ jsx(FolderTile, { section: icon.section, navIcons: navIcons2 }) : /* @__PURE__ */ jsx(AppTile, { route: icon.route, icon: navIcons2[icon.route] }),
|
|
3057
|
+
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium text-white drop-shadow-sm truncate w-full text-center", children: icon.label })
|
|
3058
|
+
]
|
|
3059
|
+
},
|
|
3060
|
+
icon.id
|
|
3061
|
+
);
|
|
3062
|
+
}) }) })
|
|
3063
|
+
] })
|
|
3064
|
+
}
|
|
3065
|
+
),
|
|
3069
3066
|
draggedIcon && dragPos && /* @__PURE__ */ jsx(
|
|
3070
3067
|
"div",
|
|
3071
3068
|
{
|
|
@@ -3075,15 +3072,9 @@ function MobileHome({
|
|
|
3075
3072
|
top: dragPos.y - dragOffsetRef.current.y,
|
|
3076
3073
|
transform: "scale(1.12)"
|
|
3077
3074
|
},
|
|
3078
|
-
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1 py-1", children: [
|
|
3079
|
-
/* @__PURE__ */ jsx(
|
|
3080
|
-
|
|
3081
|
-
{
|
|
3082
|
-
className: `relative h-[72px] w-[72px] rounded-2xl flex items-center justify-center shadow-2xl border ${draggedIcon.kind === "folder" ? "bg-white backdrop-blur border-white/40 text-blue-700" : "bg-white backdrop-blur border-white/40 text-gray-800"}`,
|
|
3083
|
-
children: draggedIcon.kind === "folder" ? sizeIcon(sectionIcons2[draggedIcon.label], FALLBACK_FOLDER_ICON) : sizeIcon(navIcons2[draggedIcon.route], FALLBACK_APP_ICON)
|
|
3084
|
-
}
|
|
3085
|
-
),
|
|
3086
|
-
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium text-white drop-shadow-md truncate max-w-[80px] text-center", children: draggedIcon.label })
|
|
3075
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1 py-1 w-20", children: [
|
|
3076
|
+
draggedIcon.kind === "folder" ? /* @__PURE__ */ jsx(FolderTile, { section: draggedIcon.section, navIcons: navIcons2 }) : /* @__PURE__ */ jsx(AppTile, { route: draggedIcon.route, icon: navIcons2[draggedIcon.route] }),
|
|
3077
|
+
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium text-white drop-shadow-md truncate w-full text-center", children: draggedIcon.label })
|
|
3087
3078
|
] })
|
|
3088
3079
|
}
|
|
3089
3080
|
),
|
|
@@ -3092,16 +3083,10 @@ function MobileHome({
|
|
|
3092
3083
|
{
|
|
3093
3084
|
folder: selectedFolder,
|
|
3094
3085
|
navIcons: navIcons2,
|
|
3095
|
-
openInFolder: openInFolder(selectedFolder),
|
|
3096
|
-
openCountByRoute,
|
|
3097
3086
|
onClose: () => setSelectedFolder(null),
|
|
3098
3087
|
onOpenApp: (path) => {
|
|
3099
3088
|
setSelectedFolder(null);
|
|
3100
3089
|
onOpenApp(path);
|
|
3101
|
-
},
|
|
3102
|
-
onActivateWindow: (id) => {
|
|
3103
|
-
setSelectedFolder(null);
|
|
3104
|
-
onActivateWindow(id);
|
|
3105
3090
|
}
|
|
3106
3091
|
}
|
|
3107
3092
|
)
|
|
@@ -3110,67 +3095,70 @@ function MobileHome({
|
|
|
3110
3095
|
function FolderPopup({
|
|
3111
3096
|
folder,
|
|
3112
3097
|
navIcons: navIcons2,
|
|
3113
|
-
openInFolder,
|
|
3114
|
-
openCountByRoute,
|
|
3115
3098
|
onClose,
|
|
3116
|
-
onOpenApp
|
|
3117
|
-
onActivateWindow
|
|
3099
|
+
onOpenApp
|
|
3118
3100
|
}) {
|
|
3101
|
+
const [closing, setClosing] = useState(false);
|
|
3102
|
+
const beginClose = () => {
|
|
3103
|
+
if (closing) return;
|
|
3104
|
+
setClosing(true);
|
|
3105
|
+
setTimeout(onClose, 200);
|
|
3106
|
+
};
|
|
3107
|
+
const closeThen = (after) => {
|
|
3108
|
+
if (closing) return;
|
|
3109
|
+
setClosing(true);
|
|
3110
|
+
setTimeout(after, 200);
|
|
3111
|
+
};
|
|
3119
3112
|
return /* @__PURE__ */ jsxs(
|
|
3120
3113
|
"div",
|
|
3121
3114
|
{
|
|
3122
|
-
className: "fixed inset-0 z-[210] flex flex-col items-center justify-center px-6 bg-black/45 backdrop-blur-xl",
|
|
3123
|
-
style: {
|
|
3124
|
-
|
|
3115
|
+
className: "fixed inset-0 z-[210] flex flex-col items-center justify-center px-6 bg-black/45 backdrop-blur-xl select-none",
|
|
3116
|
+
style: {
|
|
3117
|
+
paddingBottom: "calc(var(--mobile-bottom-nav, 70px) + 16px)",
|
|
3118
|
+
animation: closing ? "folder-fade-out 200ms ease-in forwards" : "folder-fade-in 220ms ease-out",
|
|
3119
|
+
WebkitUserSelect: "none",
|
|
3120
|
+
WebkitTouchCallout: "none"
|
|
3121
|
+
},
|
|
3122
|
+
onClick: beginClose,
|
|
3125
3123
|
children: [
|
|
3126
|
-
/* @__PURE__ */ jsx("
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
]
|
|
3144
|
-
},
|
|
3145
|
-
w.id
|
|
3146
|
-
)) })
|
|
3147
|
-
] }),
|
|
3148
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-3", children: folder.items.map((item) => {
|
|
3149
|
-
const openCount = openCountByRoute.get(item.to) ?? 0;
|
|
3124
|
+
/* @__PURE__ */ jsx("style", { children: `
|
|
3125
|
+
@keyframes folder-fade-in { from { opacity: 0; } to { opacity: 1; } }
|
|
3126
|
+
@keyframes folder-fade-out { from { opacity: 1; } to { opacity: 0; } }
|
|
3127
|
+
@keyframes folder-pop-in { from { opacity: 0; transform: scale(0.86) translateY(8px); } to { opacity: 1; transform: scale(1) translateY(0); } }
|
|
3128
|
+
@keyframes folder-pop-out { from { opacity: 1; transform: scale(1) translateY(0); } to { opacity: 0; transform: scale(0.9) translateY(4px); } }
|
|
3129
|
+
` }),
|
|
3130
|
+
/* @__PURE__ */ jsxs("div", { className: "w-full max-w-[304px]", children: [
|
|
3131
|
+
/* @__PURE__ */ jsx("h2", { className: "text-2xl font-semibold text-white drop-shadow-md mb-4 ml-4", children: folder.label }),
|
|
3132
|
+
/* @__PURE__ */ jsx(
|
|
3133
|
+
"div",
|
|
3134
|
+
{
|
|
3135
|
+
className: "max-h-[70vh] flex flex-col rounded-3xl bg-white/15 backdrop-blur-xl border border-white/25 shadow-2xl overflow-hidden",
|
|
3136
|
+
style: {
|
|
3137
|
+
animation: closing ? "folder-pop-out 180ms ease-in forwards" : "folder-pop-in 240ms cubic-bezier(0.34, 1.56, 0.64, 1)"
|
|
3138
|
+
},
|
|
3139
|
+
onClick: (e) => e.stopPropagation(),
|
|
3140
|
+
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) => {
|
|
3150
3141
|
return /* @__PURE__ */ jsxs(
|
|
3151
3142
|
"button",
|
|
3152
3143
|
{
|
|
3153
|
-
onClick: () => onOpenApp(item.to),
|
|
3154
|
-
className: "flex flex-col items-center gap-1
|
|
3144
|
+
onClick: () => closeThen(() => onOpenApp(item.to)),
|
|
3145
|
+
className: "flex flex-col items-center gap-1 py-1 rounded-lg active:bg-white/15",
|
|
3155
3146
|
children: [
|
|
3156
|
-
/* @__PURE__ */
|
|
3157
|
-
sizeIcon(navIcons2[item.to], FALLBACK_APP_ICON),
|
|
3158
|
-
openCount > 0 && /* @__PURE__ */ jsx("span", { className: "absolute -top-1 -right-1 h-2 w-2 rounded-full bg-blue-500 border-2 border-white" })
|
|
3159
|
-
] }),
|
|
3147
|
+
/* @__PURE__ */ jsx(AppTile, { route: item.to, icon: navIcons2[item.to] }),
|
|
3160
3148
|
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium text-white drop-shadow-sm truncate w-full text-center", children: item.label })
|
|
3161
3149
|
]
|
|
3162
3150
|
},
|
|
3163
3151
|
item.to
|
|
3164
3152
|
);
|
|
3165
|
-
}) })
|
|
3166
|
-
|
|
3167
|
-
|
|
3168
|
-
)
|
|
3153
|
+
}) }) })
|
|
3154
|
+
}
|
|
3155
|
+
)
|
|
3156
|
+
] })
|
|
3169
3157
|
]
|
|
3170
3158
|
}
|
|
3171
3159
|
);
|
|
3172
3160
|
}
|
|
3173
|
-
function MobileSwitcher({ windows, onActivate, onClose }) {
|
|
3161
|
+
function MobileSwitcher({ windows, onActivate, onClose, onCloseAll }) {
|
|
3174
3162
|
const [cardSize, setCardSize] = useState(() => computeCardSize());
|
|
3175
3163
|
useEffect(() => {
|
|
3176
3164
|
const onResize = () => setCardSize(computeCardSize());
|
|
@@ -3189,26 +3177,36 @@ function MobileSwitcher({ windows, onActivate, onClose }) {
|
|
|
3189
3177
|
/* @__PURE__ */ jsx("p", { className: "text-xs text-white/50", children: "Tap Home to launch one." })
|
|
3190
3178
|
] });
|
|
3191
3179
|
}
|
|
3192
|
-
return /* @__PURE__ */ jsxs("div", { className: "h-full
|
|
3193
|
-
/* @__PURE__ */ jsxs("
|
|
3194
|
-
"
|
|
3195
|
-
|
|
3180
|
+
return /* @__PURE__ */ jsxs("div", { className: "h-full flex flex-col", children: [
|
|
3181
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto px-3 pt-4 pb-4", children: [
|
|
3182
|
+
/* @__PURE__ */ jsxs("h1", { className: "text-white text-base font-semibold mb-3 px-1", children: [
|
|
3183
|
+
"Open apps \xB7 ",
|
|
3184
|
+
windows.length
|
|
3185
|
+
] }),
|
|
3186
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-3", children: windows.map((w) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-stretch gap-1", children: [
|
|
3187
|
+
/* @__PURE__ */ jsx(
|
|
3188
|
+
ThumbCard,
|
|
3189
|
+
{
|
|
3190
|
+
id: w.id,
|
|
3191
|
+
label: w.label,
|
|
3192
|
+
maxW: cardSize.w,
|
|
3193
|
+
maxH: cardSize.h,
|
|
3194
|
+
titleAbove: true,
|
|
3195
|
+
onClick: () => onActivate(w.id),
|
|
3196
|
+
onClose: () => onClose(w.id)
|
|
3197
|
+
}
|
|
3198
|
+
),
|
|
3199
|
+
/* @__PURE__ */ jsx("span", { className: "text-[11px] text-white/80 truncate px-1", children: w.label })
|
|
3200
|
+
] }, w.id)) })
|
|
3196
3201
|
] }),
|
|
3197
|
-
/* @__PURE__ */ jsx("div", { className: "
|
|
3198
|
-
|
|
3199
|
-
|
|
3200
|
-
|
|
3201
|
-
|
|
3202
|
-
|
|
3203
|
-
|
|
3204
|
-
|
|
3205
|
-
titleAbove: true,
|
|
3206
|
-
onClick: () => onActivate(w.id),
|
|
3207
|
-
onClose: () => onClose(w.id)
|
|
3208
|
-
}
|
|
3209
|
-
),
|
|
3210
|
-
/* @__PURE__ */ jsx("span", { className: "text-[11px] text-white/80 truncate px-1", children: w.label })
|
|
3211
|
-
] }, w.id)) })
|
|
3202
|
+
/* @__PURE__ */ jsx("div", { className: "shrink-0 px-3 py-3 flex justify-center", children: /* @__PURE__ */ jsx(
|
|
3203
|
+
"button",
|
|
3204
|
+
{
|
|
3205
|
+
onClick: onCloseAll,
|
|
3206
|
+
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",
|
|
3207
|
+
children: "Close All"
|
|
3208
|
+
}
|
|
3209
|
+
) })
|
|
3212
3210
|
] });
|
|
3213
3211
|
}
|
|
3214
3212
|
function computeCardSize() {
|
|
@@ -3383,6 +3381,14 @@ function MobileShell({
|
|
|
3383
3381
|
const mode = useSyncExternalStore(subscribeMobileMode, getMobileMode);
|
|
3384
3382
|
const [sheet, setSheet] = useState(null);
|
|
3385
3383
|
const unreadCount = notifications?.useUnreadCount() ?? 0;
|
|
3384
|
+
const switcherWindows = useMemo(() => {
|
|
3385
|
+
return openWindows.filter((w) => {
|
|
3386
|
+
if (!w.route) return true;
|
|
3387
|
+
const entry = WINDOW_REGISTRY[w.route];
|
|
3388
|
+
if (!entry || !isPageEntry(entry)) return true;
|
|
3389
|
+
return !entry.widget;
|
|
3390
|
+
});
|
|
3391
|
+
}, [openWindows]);
|
|
3386
3392
|
const prevOpenCountRef = useRef(openWindows.length);
|
|
3387
3393
|
useEffect(() => {
|
|
3388
3394
|
if (openWindows.length < prevOpenCountRef.current && mode === "app") {
|
|
@@ -3429,9 +3435,10 @@ function MobileShell({
|
|
|
3429
3435
|
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(
|
|
3430
3436
|
MobileSwitcher,
|
|
3431
3437
|
{
|
|
3432
|
-
windows:
|
|
3438
|
+
windows: switcherWindows,
|
|
3433
3439
|
onActivate: handleActivateWindow,
|
|
3434
|
-
onClose: (id) => closeEntity(id)
|
|
3440
|
+
onClose: (id) => closeEntity(id),
|
|
3441
|
+
onCloseAll: () => switcherWindows.forEach((w) => closeEntity(w.id))
|
|
3435
3442
|
}
|
|
3436
3443
|
) }),
|
|
3437
3444
|
sheet === "notifications" && notifications && /* @__PURE__ */ jsx(MobileNotificationSheet, { config: notifications, onClose: closeSheet }),
|
|
@@ -3451,7 +3458,6 @@ function MobileShell({
|
|
|
3451
3458
|
MobileBottomNav,
|
|
3452
3459
|
{
|
|
3453
3460
|
mode,
|
|
3454
|
-
openCount: openWindows.length,
|
|
3455
3461
|
unreadCount,
|
|
3456
3462
|
showNotifications: !!notifications,
|
|
3457
3463
|
profileAvatar: profile?.avatar_url,
|
|
@@ -3472,7 +3478,6 @@ function MobileShell({
|
|
|
3472
3478
|
}
|
|
3473
3479
|
function MobileBottomNav({
|
|
3474
3480
|
mode,
|
|
3475
|
-
openCount,
|
|
3476
3481
|
unreadCount,
|
|
3477
3482
|
showNotifications,
|
|
3478
3483
|
profileAvatar,
|
|
@@ -3482,39 +3487,43 @@ function MobileBottomNav({
|
|
|
3482
3487
|
onNotifications,
|
|
3483
3488
|
onProfile
|
|
3484
3489
|
}) {
|
|
3485
|
-
const btnClass = (active) => `flex-1 flex flex-col items-center justify-center gap-0.5 py-2 transition-colors ${active ? "text-blue-600" : "text-gray-
|
|
3490
|
+
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"}`;
|
|
3486
3491
|
return /* @__PURE__ */ jsxs(
|
|
3487
3492
|
"nav",
|
|
3488
3493
|
{
|
|
3489
|
-
className: "fixed bottom-0 inset-x-0 z-[300] flex items-stretch
|
|
3490
|
-
style: {
|
|
3494
|
+
className: "fixed bottom-0 inset-x-0 z-[300] flex items-stretch border-t border-white/40",
|
|
3495
|
+
style: {
|
|
3496
|
+
height: "var(--mobile-bottom-nav, 70px)",
|
|
3497
|
+
paddingBottom: "env(safe-area-inset-bottom)",
|
|
3498
|
+
WebkitBackdropFilter: "blur(28px) saturate(1.8)",
|
|
3499
|
+
backdropFilter: "blur(28px) saturate(1.8)",
|
|
3500
|
+
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%)",
|
|
3501
|
+
boxShadow: "inset 0 1px 0 rgba(255,255,255,0.6), 0 -2px 12px rgba(0,0,0,0.08)"
|
|
3502
|
+
},
|
|
3491
3503
|
children: [
|
|
3492
3504
|
/* @__PURE__ */ jsxs("button", { onClick: onHome, className: btnClass(mode === "home"), "aria-label": "Home", children: [
|
|
3493
|
-
/* @__PURE__ */ jsx("svg", { className: "h-
|
|
3494
|
-
/* @__PURE__ */ jsx("span", { className: "text-[
|
|
3505
|
+
/* @__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" }) }),
|
|
3506
|
+
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium", children: "Home" })
|
|
3495
3507
|
] }),
|
|
3496
3508
|
/* @__PURE__ */ jsxs("button", { onClick: onSwitcher, className: btnClass(mode === "switcher"), "aria-label": "App switcher", children: [
|
|
3497
|
-
/* @__PURE__ */ jsxs("
|
|
3498
|
-
/* @__PURE__ */
|
|
3499
|
-
|
|
3500
|
-
|
|
3501
|
-
|
|
3502
|
-
/* @__PURE__ */ jsx("rect", { x: "13.5", y: "13.5", width: "7", height: "7", rx: "1.25" })
|
|
3503
|
-
] }),
|
|
3504
|
-
openCount > 0 && /* @__PURE__ */ jsx("span", { className: "absolute -top-1 -right-2 min-w-[16px] h-4 px-1 rounded-full bg-blue-500 text-white text-[10px] font-bold leading-4 text-center", children: openCount })
|
|
3509
|
+
/* @__PURE__ */ jsxs("svg", { className: "h-8 w-8", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.7, children: [
|
|
3510
|
+
/* @__PURE__ */ jsx("rect", { x: "3.5", y: "3.5", width: "7", height: "7", rx: "1.25" }),
|
|
3511
|
+
/* @__PURE__ */ jsx("rect", { x: "13.5", y: "3.5", width: "7", height: "7", rx: "1.25" }),
|
|
3512
|
+
/* @__PURE__ */ jsx("rect", { x: "3.5", y: "13.5", width: "7", height: "7", rx: "1.25" }),
|
|
3513
|
+
/* @__PURE__ */ jsx("rect", { x: "13.5", y: "13.5", width: "7", height: "7", rx: "1.25" })
|
|
3505
3514
|
] }),
|
|
3506
|
-
/* @__PURE__ */ jsx("span", { className: "text-[
|
|
3515
|
+
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium", children: "Apps" })
|
|
3507
3516
|
] }),
|
|
3508
3517
|
showNotifications && /* @__PURE__ */ jsxs("button", { onClick: onNotifications, className: btnClass(false), "aria-label": "Notifications", children: [
|
|
3509
3518
|
/* @__PURE__ */ jsxs("span", { className: "relative", children: [
|
|
3510
|
-
/* @__PURE__ */ jsx("svg", { className: "h-
|
|
3511
|
-
unreadCount > 0 && /* @__PURE__ */ jsx("span", { className: "absolute -top-1 -right-2 min-w-[
|
|
3519
|
+
/* @__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" }) }),
|
|
3520
|
+
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 })
|
|
3512
3521
|
] }),
|
|
3513
|
-
/* @__PURE__ */ jsx("span", { className: "text-[
|
|
3522
|
+
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium", children: "Alerts" })
|
|
3514
3523
|
] }),
|
|
3515
3524
|
/* @__PURE__ */ jsxs("button", { onClick: onProfile, className: btnClass(false), "aria-label": "Profile", children: [
|
|
3516
|
-
profileAvatar ? /* @__PURE__ */ jsx("img", { src: profileAvatar, alt: "", className: "h-
|
|
3517
|
-
/* @__PURE__ */ jsx("span", { className: "text-[
|
|
3525
|
+
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 }),
|
|
3526
|
+
/* @__PURE__ */ jsx("span", { className: "text-[11px] font-medium", children: "Profile" })
|
|
3518
3527
|
] })
|
|
3519
3528
|
]
|
|
3520
3529
|
}
|
|
@@ -3855,7 +3864,7 @@ function Layout({
|
|
|
3855
3864
|
root.style.setProperty("--window-tab-font-size", sv.tabFont);
|
|
3856
3865
|
}, [inactiveHeaderOpacity, inactiveContentOpacity, activeHeaderOpacity, activeContentOpacity, taskbarH, taskbarPosition, prefs.default_window_size, prefs.window_position, prefs.menu_density, prefs.start_menu_size]);
|
|
3857
3866
|
useEffect(() => {
|
|
3858
|
-
document.documentElement.style.setProperty("--mobile-bottom-nav", isMobile ? "
|
|
3867
|
+
document.documentElement.style.setProperty("--mobile-bottom-nav", isMobile ? "100px" : "0px");
|
|
3859
3868
|
}, [isMobile]);
|
|
3860
3869
|
const [balloonDismissed, setBalloonDismissed] = useState(false);
|
|
3861
3870
|
const [isFullscreen, setIsFullscreen] = useState(!!document.fullscreenElement);
|