mirror of
https://github.com/DustinBrett/daedalOS.git
synced 2026-01-15 12:15:02 +00:00
Perf improvements to taskbar items loading
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { importAIChat } from "components/system/Taskbar/functions";
|
||||
import {
|
||||
AI_DISPLAY_TITLE,
|
||||
WINDOW_ID,
|
||||
@@ -8,6 +9,7 @@ import { DIV_BUTTON_PROPS } from "utils/constants";
|
||||
import { label } from "utils/functions";
|
||||
import useTaskbarContextMenu from "components/system/Taskbar/useTaskbarContextMenu";
|
||||
import { useSession } from "contexts/session";
|
||||
import { useMenuPreload } from "hooks/useMenuPreload";
|
||||
|
||||
type AIButtonProps = {
|
||||
aiVisible: boolean;
|
||||
@@ -15,6 +17,7 @@ type AIButtonProps = {
|
||||
};
|
||||
|
||||
const AIButton: FC<AIButtonProps> = ({ aiVisible, toggleAI }) => {
|
||||
const menuPreloadHandler = useMenuPreload(importAIChat);
|
||||
const { removeFromStack } = useSession();
|
||||
|
||||
return (
|
||||
@@ -26,6 +29,7 @@ const AIButton: FC<AIButtonProps> = ({ aiVisible, toggleAI }) => {
|
||||
{...DIV_BUTTON_PROPS}
|
||||
{...label(AI_DISPLAY_TITLE)}
|
||||
{...useTaskbarContextMenu()}
|
||||
{...menuPreloadHandler}
|
||||
>
|
||||
<AIIcon />
|
||||
</StyledAIButton>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useTheme } from "styled-components";
|
||||
import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { importCalendar } from "components/system/Taskbar/functions";
|
||||
import { measureText } from "components/system/Files/FileEntry/functions";
|
||||
import StyledClock from "components/system/Taskbar/Clock/StyledClock";
|
||||
import { type LocaleTimeDate } from "components/system/Taskbar/Clock/functions";
|
||||
@@ -14,6 +15,7 @@ import {
|
||||
TASKBAR_HEIGHT,
|
||||
} from "utils/constants";
|
||||
import { createOffscreenCanvas } from "utils/functions";
|
||||
import { useMenuPreload } from "hooks/useMenuPreload";
|
||||
|
||||
type ClockWorkerResponse = LocaleTimeDate | "source";
|
||||
|
||||
@@ -170,6 +172,7 @@ const Clock: FC<ClockProps> = ({
|
||||
},
|
||||
[toggleCalendar]
|
||||
);
|
||||
const menuPreloadHandler = useMenuPreload(importCalendar);
|
||||
|
||||
useEffect(() => {
|
||||
offScreenClockCanvas.current = undefined;
|
||||
@@ -212,6 +215,7 @@ const Clock: FC<ClockProps> = ({
|
||||
suppressHydrationWarning
|
||||
{...clockContextMenu}
|
||||
{...FOCUSABLE_ELEMENT}
|
||||
{...menuPreloadHandler}
|
||||
>
|
||||
{supportsOffscreenCanvas ? undefined : time}
|
||||
</StyledClock>
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
import { useTheme } from "styled-components";
|
||||
import { Search as SearchIcon } from "components/system/Taskbar/Search/Icons";
|
||||
import StyledTaskbarButton from "components/system/Taskbar/StyledTaskbarButton";
|
||||
import { SEARCH_BUTTON_TITLE } from "components/system/Taskbar/functions";
|
||||
import {
|
||||
importSearch,
|
||||
SEARCH_BUTTON_TITLE,
|
||||
} from "components/system/Taskbar/functions";
|
||||
import useTaskbarContextMenu from "components/system/Taskbar/useTaskbarContextMenu";
|
||||
import { DIV_BUTTON_PROPS } from "utils/constants";
|
||||
import { label } from "utils/functions";
|
||||
import { useMenuPreload } from "hooks/useMenuPreload";
|
||||
|
||||
type StartButtonProps = {
|
||||
searchVisible: boolean;
|
||||
@@ -27,6 +31,7 @@ const SearchButton: FC<StartButtonProps> = ({
|
||||
{...DIV_BUTTON_PROPS}
|
||||
{...label(SEARCH_BUTTON_TITLE)}
|
||||
{...useTaskbarContextMenu()}
|
||||
{...useMenuPreload(importSearch)}
|
||||
>
|
||||
<SearchIcon />
|
||||
</StyledTaskbarButton>
|
||||
|
||||
@@ -2,6 +2,7 @@ import { basename, extname } from "path";
|
||||
import { useTheme } from "styled-components";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { m as motion } from "motion/react";
|
||||
import dynamic from "next/dynamic";
|
||||
import { Search as SearchIcon } from "components/apps/FileExplorer/NavigationIcons";
|
||||
import {
|
||||
getCachedShortcut,
|
||||
@@ -14,9 +15,7 @@ import {
|
||||
Pictures,
|
||||
Videos,
|
||||
} from "components/system/StartMenu/Sidebar/SidebarIcons";
|
||||
import Details from "components/system/Taskbar/Search/Details";
|
||||
import { Games } from "components/system/Taskbar/Search/Icons";
|
||||
import ResultSection from "components/system/Taskbar/Search/ResultSection";
|
||||
import StyledFiles from "components/system/Taskbar/Search/StyledFiles";
|
||||
import StyledResults from "components/system/Taskbar/Search/StyledResults";
|
||||
import StyledSearch from "components/system/Taskbar/Search/StyledSearch";
|
||||
@@ -95,6 +94,13 @@ const METADATA = {
|
||||
},
|
||||
} as Record<TabName, TabData>;
|
||||
|
||||
const Details = dynamic(
|
||||
() => import("components/system/Taskbar/Search/Details")
|
||||
);
|
||||
const ResultSection = dynamic(
|
||||
() => import("components/system/Taskbar/Search/ResultSection")
|
||||
);
|
||||
|
||||
const Search: FC<SearchProps> = ({ toggleSearch }) => {
|
||||
const inputRef = useRef<HTMLInputElement | null>(null);
|
||||
const menuRef = useRef<HTMLElement | null>(null);
|
||||
|
||||
@@ -1,37 +1,36 @@
|
||||
import { useCallback, useRef, useState } from "react";
|
||||
import { useCallback } from "react";
|
||||
import StartButtonIcon from "components/system/Taskbar/StartButton/StartButtonIcon";
|
||||
import StyledTaskbarButton from "components/system/Taskbar/StyledTaskbarButton";
|
||||
import { START_BUTTON_TITLE } from "components/system/Taskbar/functions";
|
||||
import {
|
||||
importStartMenu,
|
||||
START_BUTTON_TITLE,
|
||||
} from "components/system/Taskbar/functions";
|
||||
import useTaskbarContextMenu from "components/system/Taskbar/useTaskbarContextMenu";
|
||||
import { DIV_BUTTON_PROPS } from "utils/constants";
|
||||
import { label, preloadImage } from "utils/functions";
|
||||
import { useMenuPreload } from "hooks/useMenuPreload";
|
||||
|
||||
type StartButtonProps = {
|
||||
startMenuVisible: boolean;
|
||||
toggleStartMenu: (showMenu?: boolean) => void;
|
||||
};
|
||||
|
||||
const preloadStartMenu = async (): Promise<void> => {
|
||||
const preloadedStartMenu = importStartMenu();
|
||||
const { default: startMenuIcons } =
|
||||
(await import("public/.index/startMenuIcons.json")) || {};
|
||||
|
||||
startMenuIcons?.forEach((icon) => preloadImage(icon));
|
||||
|
||||
await preloadedStartMenu;
|
||||
};
|
||||
|
||||
const StartButton: FC<StartButtonProps> = ({
|
||||
startMenuVisible,
|
||||
toggleStartMenu,
|
||||
}) => {
|
||||
const [preloaded, setPreloaded] = useState(false);
|
||||
const initalizedPreload = useRef(false);
|
||||
const preloadIcons = useCallback(async (): Promise<void> => {
|
||||
if (initalizedPreload.current) return;
|
||||
initalizedPreload.current = true;
|
||||
|
||||
const startMenuIcons = (await import("public/.index/startMenuIcons.json"))
|
||||
.default;
|
||||
|
||||
startMenuIcons?.forEach((icon) => preloadImage(icon));
|
||||
|
||||
setPreloaded(true);
|
||||
}, []);
|
||||
const onClick = useCallback(
|
||||
async ({ ctrlKey, shiftKey }: React.MouseEvent): Promise<void> => {
|
||||
if (!preloaded) preloadIcons();
|
||||
|
||||
toggleStartMenu();
|
||||
|
||||
if (ctrlKey && shiftKey) {
|
||||
@@ -40,18 +39,18 @@ const StartButton: FC<StartButtonProps> = ({
|
||||
spawnSheep();
|
||||
}
|
||||
},
|
||||
[preloadIcons, preloaded, toggleStartMenu]
|
||||
[toggleStartMenu]
|
||||
);
|
||||
|
||||
return (
|
||||
<StyledTaskbarButton
|
||||
$active={startMenuVisible}
|
||||
onClick={onClick}
|
||||
onMouseOver={preloaded ? undefined : preloadIcons}
|
||||
$highlight
|
||||
{...DIV_BUTTON_PROPS}
|
||||
{...label(START_BUTTON_TITLE)}
|
||||
{...useTaskbarContextMenu(true)}
|
||||
{...useMenuPreload(preloadStartMenu)}
|
||||
>
|
||||
<StartButtonIcon />
|
||||
</StyledTaskbarButton>
|
||||
|
||||
@@ -3,6 +3,16 @@ import { PREVENT_SCROLL } from "utils/constants";
|
||||
export const START_BUTTON_TITLE = "Start";
|
||||
export const SEARCH_BUTTON_TITLE = "Type here to search";
|
||||
|
||||
/* eslint-disable @typescript-eslint/explicit-function-return-type, @typescript-eslint/explicit-module-boundary-types */
|
||||
export const importAIButton = () =>
|
||||
import("components/system/Taskbar/AI/AIButton");
|
||||
export const importAIChat = () => import("components/system/Taskbar/AI/AIChat");
|
||||
export const importCalendar = () =>
|
||||
import("components/system/Taskbar/Calendar");
|
||||
export const importSearch = () => import("components/system/Taskbar/Search");
|
||||
export const importStartMenu = () => import("components/system/StartMenu");
|
||||
/* eslint-enable @typescript-eslint/explicit-function-return-type */
|
||||
|
||||
export const maybeCloseTaskbarMenu = (
|
||||
{ relatedTarget: focusedElement }: React.FocusEvent<HTMLElement>,
|
||||
menuElement: HTMLElement | null,
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
import { memo, useCallback, useState } from "react";
|
||||
import dynamic from "next/dynamic";
|
||||
import { AnimatePresence } from "motion/react";
|
||||
import {
|
||||
importAIButton,
|
||||
importAIChat,
|
||||
importCalendar,
|
||||
importSearch,
|
||||
importStartMenu,
|
||||
} from "components/system/Taskbar/functions";
|
||||
import Clock from "components/system/Taskbar/Clock";
|
||||
import SearchButton from "components/system/Taskbar/Search/SearchButton";
|
||||
import StartButton from "components/system/Taskbar/StartButton";
|
||||
@@ -11,11 +18,11 @@ import { CLOCK_CANVAS_BASE_WIDTH, FOCUSABLE_ELEMENT } from "utils/constants";
|
||||
import { useWindowAI } from "hooks/useWindowAI";
|
||||
import { useSession } from "contexts/session";
|
||||
|
||||
const AIButton = dynamic(() => import("components/system/Taskbar/AI/AIButton"));
|
||||
const AIChat = dynamic(() => import("components/system/Taskbar/AI/AIChat"));
|
||||
const Calendar = dynamic(() => import("components/system/Taskbar/Calendar"));
|
||||
const Search = dynamic(() => import("components/system/Taskbar/Search"));
|
||||
const StartMenu = dynamic(() => import("components/system/StartMenu"));
|
||||
const AIButton = dynamic(importAIButton);
|
||||
const AIChat = dynamic(importAIChat);
|
||||
const Calendar = dynamic(importCalendar);
|
||||
const Search = dynamic(importSearch);
|
||||
const StartMenu = dynamic(importStartMenu);
|
||||
|
||||
const Taskbar: FC = () => {
|
||||
const [startMenuVisible, setStartMenuVisible] = useState(false);
|
||||
|
||||
19
hooks/useMenuPreload.ts
Normal file
19
hooks/useMenuPreload.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { useState, useRef, useCallback } from "react";
|
||||
|
||||
export const useMenuPreload = (
|
||||
preloadCallback: () => Promise<unknown>
|
||||
): {
|
||||
onMouseOver?: React.MouseEventHandler<HTMLButtonElement | HTMLDivElement>;
|
||||
} => {
|
||||
const [preloaded, setPreloaded] = useState(false);
|
||||
const initalizedPreload = useRef(false);
|
||||
const preloadMenu = useCallback((): void => {
|
||||
if (initalizedPreload.current) return;
|
||||
|
||||
initalizedPreload.current = true;
|
||||
|
||||
preloadCallback().then(() => setPreloaded(true));
|
||||
}, [preloadCallback]);
|
||||
|
||||
return preloaded ? {} : { onMouseOver: preloadMenu };
|
||||
};
|
||||
Reference in New Issue
Block a user