Memoize more stuff

This commit is contained in:
Dustin Brett 2025-04-23 21:04:20 -07:00
parent 0405c6ba7d
commit f434256a31
4 changed files with 66 additions and 53 deletions

View File

@ -331,6 +331,21 @@ const FileEntry: FC<FileEntryProps> = ({
.forEach(({ icon: image }) => image && preloadImage(image))
);
}, [path, readdir]);
const onMouseOverButton = useCallback(() => {
if (listView && isDirectory) preloadImages();
createTooltip().then(setTooltip);
}, [createTooltip, isDirectory, listView, preloadImages]);
const lockWidthStyle = useMemo(
() => ({ maxWidth: columnWidth, minWidth: columnWidth }),
[columnWidth]
);
const renameFile = useCallback(
(origPath: string, newName?: string) => {
fileActions.renameFile(origPath, newName);
setRenaming("");
},
[fileActions, setRenaming]
);
useEffect(() => {
if (!isLoadingFileManager && isVisible && !isIconCached.current) {
@ -569,10 +584,7 @@ const FileEntry: FC<FileEntryProps> = ({
<Button
ref={buttonRef}
aria-label={name}
onMouseOverCapture={() => {
if (listView && isDirectory) preloadImages();
createTooltip().then(setTooltip);
}}
onMouseOverCapture={onMouseOverButton}
title={tooltip}
{...(listView && { ...LIST_VIEW_ANIMATION, as: motion.button })}
{...useDoubleClick(doubleClickHandler, listView)}
@ -598,11 +610,7 @@ const FileEntry: FC<FileEntryProps> = ({
[listView]
)}
$renaming={renaming}
style={
showColumn
? { maxWidth: columnWidth, minWidth: columnWidth }
: undefined
}
style={showColumn ? lockWidthStyle : undefined}
{...(isHeading && {
"aria-level": 1,
role: "heading",
@ -629,10 +637,7 @@ const FileEntry: FC<FileEntryProps> = ({
isDesktop={isDesktop}
name={name}
path={path}
renameFile={(origPath, newName) => {
fileActions.renameFile(origPath, newName);
setRenaming("");
}}
renameFile={renameFile}
setRenaming={setRenaming}
view={view}
/>

View File

@ -1,5 +1,5 @@
import { useTheme } from "styled-components";
import { memo } from "react";
import { memo, useCallback } from "react";
import StyledSearchButton from "components/system/Taskbar/Search/StyledSearchButton";
import {
importSearch,
@ -28,12 +28,13 @@ const SearchButton: FC<StartButtonProps> = ({
const {
sizes: { taskbar },
} = useTheme();
const onClick = useCallback(() => toggleSearch(), [toggleSearch]);
return (
<StyledSearchButton
$active={searchVisible}
$left={taskbar.button.width}
onClick={() => toggleSearch()}
onClick={onClick}
{...DIV_BUTTON_PROPS}
{...label(SEARCH_BUTTON_TITLE)}
{...useTaskbarContextMenu()}

View File

@ -114,6 +114,7 @@ const Titlebar: FC<TitlebarProps> = ({ id }) => {
},
[onClickClose, resetMenu, titlebarContextMenu]
);
const triggerMinimize = useCallback(() => onMinimize(), [onMinimize]);
const onIconMouseDownCapture = useCallback<
React.MouseEventHandler<HTMLImageElement>
>(() => {
@ -154,7 +155,7 @@ const Titlebar: FC<TitlebarProps> = ({ id }) => {
{!hideMinimizeButton && (
<Button
className="minimize"
onClick={() => onMinimize()}
onClick={triggerMinimize}
{...label("Minimize")}
>
<MinimizeIcon />

View File

@ -1,4 +1,4 @@
import { memo, useEffect, useMemo, useState } from "react";
import { memo, useCallback, useEffect, useMemo, useState } from "react";
import styled from "styled-components";
import { SUPPORTED_ICON_PIXEL_RATIOS } from "utils/constants";
import {
@ -83,6 +83,29 @@ const Icon: FCWithRef<
};
}, [displaySize, imgSize]);
const [failedUrls, setFailedUrls] = useState<string[]>([]);
const onError: React.ReactEventHandler<HTMLImageElement> = useCallback(
({ target }) => {
const { currentSrc = "" } = (target as HTMLImageElement) || {};
try {
const { pathname } = new URL(currentSrc);
if (pathname && !failedUrls.includes(pathname)) {
setFailedUrls((currentFailedUrls) => [
...currentFailedUrls,
pathname,
]);
}
} catch {
// Ignore failure to log failed url
}
},
[failedUrls]
);
const onLoad: React.ReactEventHandler<HTMLImageElement> = useCallback(
() => setLoaded(true),
[]
);
useEffect(
() => () => {
@ -91,41 +114,6 @@ const Icon: FCWithRef<
[loaded, src]
);
const RenderedIcon = (
<StyledIcon
ref={ref}
$loaded={loaded}
onError={({ target }) => {
const { currentSrc = "" } = (target as HTMLImageElement) || {};
try {
const { pathname } = new URL(currentSrc);
if (pathname && !failedUrls.includes(pathname)) {
setFailedUrls((currentFailedUrls) => [
...currentFailedUrls,
pathname,
]);
}
} catch {
// Ignore failure to log failed url
}
}}
onLoad={() => setLoaded(true)}
src={isDynamic ? imageSrc(imgSrc, imgSize, 1, srcExt) : src || undefined}
srcSet={
!singleSrc && isDynamic
? imageSrcs(imgSrc, imgSize, srcExt, failedUrls) ||
(failedUrls.length === 0
? ""
: createFallbackSrcSet(imgSrc, failedUrls))
: undefined
}
{...componentProps}
{...dimensionProps}
/>
);
return (
<picture>
{!singleSrc &&
@ -155,7 +143,25 @@ const Icon: FCWithRef<
/>
);
})}
{RenderedIcon}
<StyledIcon
ref={ref}
$loaded={loaded}
onError={onError}
onLoad={onLoad}
src={
isDynamic ? imageSrc(imgSrc, imgSize, 1, srcExt) : src || undefined
}
srcSet={
!singleSrc && isDynamic
? imageSrcs(imgSrc, imgSize, srcExt, failedUrls) ||
(failedUrls.length === 0
? ""
: createFallbackSrcSet(imgSrc, failedUrls))
: undefined
}
{...componentProps}
{...dimensionProps}
/>
</picture>
);
};