From a144d3b2fcf118a3d0c6d0be00bd880e13c05cb2 Mon Sep 17 00:00:00 2001 From: Dustin Brett Date: Sat, 2 Jul 2022 19:57:02 -0700 Subject: [PATCH] Avif by default + preloading tweaks --- components/apps/FileExplorer/index.tsx | 4 +- .../apps/VideoPlayer/StyledVideoPlayer.ts | 2 +- components/pages/Metadata.tsx | 58 +++++++++++--- components/system/Dialogs/Run/index.tsx | 2 +- .../system/Files/FileEntry/functions.ts | 6 +- components/system/StartMenu/Sidebar/index.tsx | 6 +- .../system/Taskbar/StartButton/index.tsx | 13 ++-- contexts/process/directory.ts | 40 +++++----- public/Users/Public/Desktop/My PC.url | 2 +- public/Users/Public/Desktop/desktop.ini | 2 +- public/Users/Public/Documents/desktop.ini | 2 +- public/Users/Public/Music/desktop.ini | 2 +- public/Users/Public/Pictures/desktop.ini | 2 +- public/Users/Public/Start Menu/Browser.url | 2 +- public/Users/Public/Start Menu/DevTools.url | 2 +- public/Users/Public/Start Menu/Marked.url | 2 +- .../Users/Public/Start Menu/Monaco Editor.url | 2 +- public/Users/Public/Start Menu/PDF.url | 2 +- .../Users/Public/Start Menu/Photo Viewer.url | 2 +- public/Users/Public/Start Menu/Terminal.url | 2 +- public/Users/Public/Start Menu/TinyMCE.url | 2 +- .../Users/Public/Start Menu/Video Player.url | 2 +- public/Users/Public/Start Menu/Vim.url | 2 +- public/Users/Public/Start Menu/Webamp.url | 2 +- public/Users/Public/Videos/desktop.ini | 2 +- public/Users/Public/desktop.ini | 2 +- scripts/preloadIcons.js | 9 ++- styles/common/Icon.tsx | 21 +----- utils/constants.ts | 19 +++-- utils/functions.ts | 75 ++++++++++++++++++- 30 files changed, 197 insertions(+), 94 deletions(-) diff --git a/components/apps/FileExplorer/index.tsx b/components/apps/FileExplorer/index.tsx index b3125b61..c8e853c6 100644 --- a/components/apps/FileExplorer/index.tsx +++ b/components/apps/FileExplorer/index.tsx @@ -45,7 +45,7 @@ const FileExplorer: FC = ({ id }) => { } else if (fs) { setProcessIcon( id, - `/System/Icons/${directoryName ? "folder" : "pc"}.webp` + `/System/Icons/${directoryName ? "folder" : "pc"}.avif` ); getIconFromIni(fs, url).then((iconFile) => { if (iconFile) setProcessIcon(id, iconFile); @@ -56,7 +56,7 @@ const FileExplorer: FC = ({ id }) => { } } else { setProcessUrl(id, "/"); - setProcessIcon(id, "/System/Icons/pc.webp"); + setProcessIcon(id, "/System/Icons/pc.avif"); } }, [ currentUrl, diff --git a/components/apps/VideoPlayer/StyledVideoPlayer.ts b/components/apps/VideoPlayer/StyledVideoPlayer.ts index 538364c9..5158889b 100644 --- a/components/apps/VideoPlayer/StyledVideoPlayer.ts +++ b/components/apps/VideoPlayer/StyledVideoPlayer.ts @@ -167,7 +167,7 @@ const StyledVideoPlayer = styled.div` } video { - background-image: url("/System/Icons/48x48/vlc.webp"); + background-image: url("/System/Icons/48x48/vlc.avif"); background-position: center calc(50% - 15px); background-repeat: no-repeat; padding-bottom: 30px; diff --git a/components/pages/Metadata.tsx b/components/pages/Metadata.tsx index a3e7b6c1..25fb241c 100644 --- a/components/pages/Metadata.tsx +++ b/components/pages/Metadata.tsx @@ -1,17 +1,53 @@ import Head from "next/head"; -import { PACKAGE_DATA } from "utils/constants"; +import desktopIcons from "public/.index/desktopIcons.json"; +import { useEffect, useState } from "react"; +import { + HIGH_PRIORITY_ELEMENT, + ICON_PATH, + PACKAGE_DATA, + USER_ICON_PATH, +} from "utils/constants"; +import type { ImageFormat } from "utils/functions"; +import { detectImageFormat, imageSrcs } from "utils/functions"; const { alias, description } = PACKAGE_DATA; -const Metadata: FC = () => ( - - - - {alias} - -); +const Metadata: FC = () => { + const [imgFormat, setImgFormat] = useState(); + + useEffect(() => { + detectImageFormat().then(setImgFormat); + }, []); + + return ( + + + + {alias} + {imgFormat && + desktopIcons.map((icon) => { + const isStaticIcon = + !icon.startsWith(ICON_PATH) && !icon.startsWith(USER_ICON_PATH); + + return ( + + ); + })} + + ); +}; export default Metadata; diff --git a/components/system/Dialogs/Run/index.tsx b/components/system/Dialogs/Run/index.tsx index 11cbc5e4..1514a707 100644 --- a/components/system/Dialogs/Run/index.tsx +++ b/components/system/Dialogs/Run/index.tsx @@ -149,7 +149,7 @@ const Run: FC = () => { return (
- Run + Run
{MESSAGE}
diff --git a/components/system/Files/FileEntry/functions.ts b/components/system/Files/FileEntry/functions.ts index 19169461..84ceb772 100644 --- a/components/system/Files/FileEntry/functions.ts +++ b/components/system/Files/FileEntry/functions.ts @@ -102,7 +102,7 @@ export const getIconByFileExtension = (extension: string): string => { const { icon: extensionIcon = "", process: [defaultProcess = ""] = [] } = extension in extensions ? extensions[extension as ExtensionType] : {}; - if (extensionIcon) return `/System/Icons/${extensionIcon}.webp`; + if (extensionIcon) return `/System/Icons/${extensionIcon}.avif`; return ( processDirectory[defaultProcess || getDefaultFileViewer(extension)]?.icon || @@ -335,7 +335,7 @@ export const getInfoWithExtension = ( }) ); } else if (extension === ".exe") { - getInfoByFileExtension("/System/Icons/executable.webp", (signal) => + getInfoByFileExtension("/System/Icons/executable.avif", (signal) => fs.readFile(path, async (error, contents = Buffer.from("")) => { if (!error && contents.length > 0 && !signal.aborted) { const exeIcon = await extractExeIcon(contents); @@ -468,7 +468,7 @@ export const getInfoWithExtension = ( }); } else if (extension === ".mp3") { getInfoByFileExtension( - `/System/Icons/${extensions[".mp3"].icon as string}.webp`, + `/System/Icons/${extensions[".mp3"].icon as string}.avif`, (signal) => fs.readFile(path, (error, contents = Buffer.from("")) => { if (!error && !signal.aborted) { diff --git a/components/system/StartMenu/Sidebar/index.tsx b/components/system/StartMenu/Sidebar/index.tsx index d2fe4082..3838fda3 100644 --- a/components/system/StartMenu/Sidebar/index.tsx +++ b/components/system/StartMenu/Sidebar/index.tsx @@ -58,7 +58,7 @@ const Sidebar: FC = ({ height }) => { open( "FileExplorer", { url: `${HOME}/Documents` }, - "/System/Icons/documents.webp" + "/System/Icons/documents.avif" ), icon: , name: "Documents", @@ -69,7 +69,7 @@ const Sidebar: FC = ({ height }) => { open( "FileExplorer", { url: `${HOME}/Pictures` }, - "/System/Icons/pictures.webp" + "/System/Icons/pictures.avif" ), icon: , name: "Pictures", @@ -80,7 +80,7 @@ const Sidebar: FC = ({ height }) => { open( "FileExplorer", { url: `${HOME}/Videos` }, - "/System/Icons/videos.webp" + "/System/Icons/videos.avif" ), icon: , name: "Videos", diff --git a/components/system/Taskbar/StartButton/index.tsx b/components/system/Taskbar/StartButton/index.tsx index 728d1d16..6f7f851a 100644 --- a/components/system/Taskbar/StartButton/index.tsx +++ b/components/system/Taskbar/StartButton/index.tsx @@ -1,11 +1,10 @@ import StartButtonIcon from "components/system/Taskbar/StartButton/StartButtonIcon"; import StyledStartButton from "components/system/Taskbar/StartButton/StyledStartButton"; import useTaskbarContextMenu from "components/system/Taskbar/useTaskbarContextMenu"; -import { basename, dirname, join } from "path"; import startMenuIcons from "public/.index/startMenuIcons.json"; import { useState } from "react"; import { ICON_PATH, USER_ICON_PATH } from "utils/constants"; -import { label } from "utils/functions"; +import { imageSrcs, label } from "utils/functions"; type StartButtonProps = { startMenuVisible: boolean; @@ -22,17 +21,17 @@ const StartButton: FC = ({ const link = document.createElement( "link" ) as HTMLElementWithPriority; + const imgFormat = window.IMAGE_FORMAT || "png"; link.as = "image"; link.fetchpriority = "high"; link.rel = "preload"; - link.href = icon; + link.type = `image/${imgFormat}`; if (icon.startsWith(ICON_PATH) || icon.startsWith(USER_ICON_PATH)) { - link.href = join(dirname(icon), `48x48`, basename(icon)).replace( - /\\/g, - "/" - ); + link.imageSrcset = imageSrcs(icon, 48, `.${imgFormat}`); + } else { + link.href = icon; } document.head.appendChild(link); diff --git a/contexts/process/directory.ts b/contexts/process/directory.ts index ebd4bd85..af46705d 100644 --- a/contexts/process/directory.ts +++ b/contexts/process/directory.ts @@ -11,7 +11,7 @@ const processDirectory: Processes = { height: 480, width: 640, }, - icon: "/System/Icons/boxedwine.webp", + icon: "/System/Icons/boxedwine.avif", singleton: true, title: "BoxedWine", }, @@ -22,7 +22,7 @@ const processDirectory: Processes = { height: 480, width: 640, }, - icon: "/System/Icons/chromium.webp", + icon: "/System/Icons/chromium.avif", title: "Browser", }, Byuu: { @@ -33,7 +33,7 @@ const processDirectory: Processes = { height: 240, width: 256, }, - icon: "/System/Icons/byuu.webp", + icon: "/System/Icons/byuu.avif", lockAspectRatio: true, title: "Byuu", }, @@ -44,7 +44,7 @@ const processDirectory: Processes = { height: 480, width: 640, }, - icon: "/System/Icons/dxball.webp", + icon: "/System/Icons/dxball.avif", lockAspectRatio: true, title: "DX-Ball", }, @@ -55,7 +55,7 @@ const processDirectory: Processes = { height: 380, width: 545, }, - icon: "/System/Icons/eruda.webp", + icon: "/System/Icons/eruda.avif", singleton: true, title: "DevTools", }, @@ -73,7 +73,7 @@ const processDirectory: Processes = { height: 200, width: 320, }, - icon: "/System/Icons/jsdos.webp", + icon: "/System/Icons/jsdos.avif", lockAspectRatio: true, title: "js-dos v7", }, @@ -84,7 +84,7 @@ const processDirectory: Processes = { height: 480, width: 560, }, - icon: "/System/Icons/marked.webp", + icon: "/System/Icons/marked.avif", title: "Marked", }, MonacoEditor: { @@ -94,7 +94,7 @@ const processDirectory: Processes = { height: 480, width: 544, }, - icon: "/System/Icons/monaco.webp", + icon: "/System/Icons/monaco.avif", title: "Monaco Editor", }, PDF: { @@ -104,7 +104,7 @@ const processDirectory: Processes = { height: 480, width: 640, }, - icon: "/System/Icons/pdf.webp", + icon: "/System/Icons/pdf.avif", title: "PDF", }, Photos: { @@ -115,7 +115,7 @@ const processDirectory: Processes = { width: 576, }, hideTitlebarIcon: true, - icon: "/System/Icons/photos.webp", + icon: "/System/Icons/photos.avif", prependTaskbarTitle: true, title: "Photos", }, @@ -126,7 +126,7 @@ const processDirectory: Processes = { height: 400, width: 550, }, - icon: "/System/Icons/ruffle.webp", + icon: "/System/Icons/ruffle.avif", lockAspectRatio: true, title: "Ruffle", }, @@ -139,7 +139,7 @@ const processDirectory: Processes = { }, hideMaximizeButton: true, hideMinimizeButton: true, - icon: "/System/Icons/run.webp", + icon: "/System/Icons/run.avif", initialRelativePosition: { bottom: TASKBAR_HEIGHT + 11, left: 15, @@ -154,7 +154,7 @@ const processDirectory: Processes = { height: 440, width: 600, }, - icon: "/System/Icons/pinball.webp", + icon: "/System/Icons/pinball.avif", lockAspectRatio: true, singleton: true, title: "Space Cadet", @@ -166,7 +166,7 @@ const processDirectory: Processes = { height: 340, width: 553, }, - icon: "/System/Icons/xterm.webp", + icon: "/System/Icons/xterm.avif", lockAspectRatio: true, title: "Terminal", }, @@ -177,7 +177,7 @@ const processDirectory: Processes = { height: 480, width: 640, }, - icon: "/System/Icons/tinymce.webp", + icon: "/System/Icons/tinymce.avif", singleton: true, title: "TinyMCE", }, @@ -189,7 +189,7 @@ const processDirectory: Processes = { height: 163, width: 400, }, - icon: "/System/Icons/copying.webp", + icon: "/System/Icons/copying.avif", title: "Dialog", }, V86: { @@ -201,7 +201,7 @@ const processDirectory: Processes = { height: 200, width: 320, }, - icon: "/System/Icons/v86.webp", + icon: "/System/Icons/v86.avif", singleton: true, title: "Virtual x86", }, @@ -209,7 +209,7 @@ const processDirectory: Processes = { Component: dynamic(() => import("components/apps/VideoPlayer")), autoSizing: true, background: "#000", - icon: "/System/Icons/vlc.webp", + icon: "/System/Icons/vlc.avif", title: "Video Player", }, Vim: { @@ -220,7 +220,7 @@ const processDirectory: Processes = { height: 448, width: 595, }, - icon: "/System/Icons/vim.webp", + icon: "/System/Icons/vim.avif", singleton: true, title: "Vim", }, @@ -228,7 +228,7 @@ const processDirectory: Processes = { Component: dynamic(() => import("components/apps/Webamp")), allowResizing: false, hasWindow: false, - icon: "/System/Icons/webamp.webp", + icon: "/System/Icons/webamp.avif", singleton: true, title: "Webamp", }, diff --git a/public/Users/Public/Desktop/My PC.url b/public/Users/Public/Desktop/My PC.url index d2843eb5..162dea3d 100644 --- a/public/Users/Public/Desktop/My PC.url +++ b/public/Users/Public/Desktop/My PC.url @@ -1,6 +1,6 @@ [InternetShortcut] BaseURL=FileExplorer Comment=Shows the contents of the root folder. -IconFile=/System/Icons/pc.webp +IconFile=/System/Icons/pc.avif Type=System URL=/ diff --git a/public/Users/Public/Desktop/desktop.ini b/public/Users/Public/Desktop/desktop.ini index a5055c9f..b6757347 100644 --- a/public/Users/Public/Desktop/desktop.ini +++ b/public/Users/Public/Desktop/desktop.ini @@ -1,2 +1,2 @@ [ShellClassInfo] -IconFile=/System/Icons/desktop.webp +IconFile=/System/Icons/desktop.avif diff --git a/public/Users/Public/Documents/desktop.ini b/public/Users/Public/Documents/desktop.ini index dc3e08f4..f97c02dd 100644 --- a/public/Users/Public/Documents/desktop.ini +++ b/public/Users/Public/Documents/desktop.ini @@ -1,2 +1,2 @@ [ShellClassInfo] -IconFile=/System/Icons/documents.webp +IconFile=/System/Icons/documents.avif diff --git a/public/Users/Public/Music/desktop.ini b/public/Users/Public/Music/desktop.ini index 5ebf654e..9dd9866e 100644 --- a/public/Users/Public/Music/desktop.ini +++ b/public/Users/Public/Music/desktop.ini @@ -1,2 +1,2 @@ [ShellClassInfo] -IconFile=/System/Icons/music.webp +IconFile=/System/Icons/music.avif diff --git a/public/Users/Public/Pictures/desktop.ini b/public/Users/Public/Pictures/desktop.ini index d060e74c..63c5185f 100644 --- a/public/Users/Public/Pictures/desktop.ini +++ b/public/Users/Public/Pictures/desktop.ini @@ -1,2 +1,2 @@ [ShellClassInfo] -IconFile=/System/Icons/pictures.webp +IconFile=/System/Icons/pictures.avif diff --git a/public/Users/Public/Start Menu/Browser.url b/public/Users/Public/Start Menu/Browser.url index 21c63bda..f47e2872 100644 --- a/public/Users/Public/Start Menu/Browser.url +++ b/public/Users/Public/Start Menu/Browser.url @@ -1,4 +1,4 @@ [InternetShortcut] BaseURL=Browser Comment=Access the Internet -IconFile=/System/Icons/chromium.webp +IconFile=/System/Icons/chromium.avif diff --git a/public/Users/Public/Start Menu/DevTools.url b/public/Users/Public/Start Menu/DevTools.url index 2297fa84..0b659972 100644 --- a/public/Users/Public/Start Menu/DevTools.url +++ b/public/Users/Public/Start Menu/DevTools.url @@ -1,4 +1,4 @@ [InternetShortcut] BaseURL=DevTools Comment=Developer Tools Console -IconFile=/System/Icons/eruda.webp +IconFile=/System/Icons/eruda.avif diff --git a/public/Users/Public/Start Menu/Marked.url b/public/Users/Public/Start Menu/Marked.url index d789cd43..fafe45a1 100644 --- a/public/Users/Public/Start Menu/Marked.url +++ b/public/Users/Public/Start Menu/Marked.url @@ -2,4 +2,4 @@ BaseURL=Marked Comment=Markdown Viewer URL=/CREDITS.md -IconFile=/System/Icons/marked.webp +IconFile=/System/Icons/marked.avif diff --git a/public/Users/Public/Start Menu/Monaco Editor.url b/public/Users/Public/Start Menu/Monaco Editor.url index 07cb6abe..94e8e37d 100644 --- a/public/Users/Public/Start Menu/Monaco Editor.url +++ b/public/Users/Public/Start Menu/Monaco Editor.url @@ -1,4 +1,4 @@ [InternetShortcut] BaseURL=MonacoEditor Comment=Text Editor -IconFile=/System/Icons/monaco.webp +IconFile=/System/Icons/monaco.avif diff --git a/public/Users/Public/Start Menu/PDF.url b/public/Users/Public/Start Menu/PDF.url index e488d4d1..55d583a1 100644 --- a/public/Users/Public/Start Menu/PDF.url +++ b/public/Users/Public/Start Menu/PDF.url @@ -1,4 +1,4 @@ [InternetShortcut] BaseURL=PDF Comment=View PDF Documents -IconFile=/System/Icons/pdf.webp +IconFile=/System/Icons/pdf.avif diff --git a/public/Users/Public/Start Menu/Photo Viewer.url b/public/Users/Public/Start Menu/Photo Viewer.url index 4fb037d7..b47d5c6d 100644 --- a/public/Users/Public/Start Menu/Photo Viewer.url +++ b/public/Users/Public/Start Menu/Photo Viewer.url @@ -1,4 +1,4 @@ [InternetShortcut] BaseURL=Photos Comment=Photo Viewer -IconFile=/System/Icons/photos.webp +IconFile=/System/Icons/photos.avif diff --git a/public/Users/Public/Start Menu/Terminal.url b/public/Users/Public/Start Menu/Terminal.url index 667a12d2..e2872298 100644 --- a/public/Users/Public/Start Menu/Terminal.url +++ b/public/Users/Public/Start Menu/Terminal.url @@ -1,4 +1,4 @@ [InternetShortcut] BaseURL=Terminal Comment=Command Prompt -IconFile=/System/Icons/xterm.webp +IconFile=/System/Icons/xterm.avif diff --git a/public/Users/Public/Start Menu/TinyMCE.url b/public/Users/Public/Start Menu/TinyMCE.url index 869b7ff2..0127a61a 100644 --- a/public/Users/Public/Start Menu/TinyMCE.url +++ b/public/Users/Public/Start Menu/TinyMCE.url @@ -1,4 +1,4 @@ [InternetShortcut] BaseURL=TinyMCE Comment=WYSIWYG Editor -IconFile=/System/Icons/tinymce.webp +IconFile=/System/Icons/tinymce.avif diff --git a/public/Users/Public/Start Menu/Video Player.url b/public/Users/Public/Start Menu/Video Player.url index 389fc5c1..46b66524 100644 --- a/public/Users/Public/Start Menu/Video Player.url +++ b/public/Users/Public/Start Menu/Video Player.url @@ -1,4 +1,4 @@ [InternetShortcut] BaseURL=VideoPlayer Comment=Video Player -IconFile=/System/Icons/vlc.webp +IconFile=/System/Icons/vlc.avif diff --git a/public/Users/Public/Start Menu/Vim.url b/public/Users/Public/Start Menu/Vim.url index 8aafaba7..0fc274ae 100644 --- a/public/Users/Public/Start Menu/Vim.url +++ b/public/Users/Public/Start Menu/Vim.url @@ -1,4 +1,4 @@ [InternetShortcut] BaseURL=Vim Comment=Text Editor -IconFile=/System/Icons/vim.webp +IconFile=/System/Icons/vim.avif diff --git a/public/Users/Public/Start Menu/Webamp.url b/public/Users/Public/Start Menu/Webamp.url index 6a8ce6a2..b54fbdc8 100644 --- a/public/Users/Public/Start Menu/Webamp.url +++ b/public/Users/Public/Start Menu/Webamp.url @@ -1,4 +1,4 @@ [InternetShortcut] BaseURL=Webamp Comment=Audio Player -IconFile=/System/Icons/webamp.webp +IconFile=/System/Icons/webamp.avif diff --git a/public/Users/Public/Videos/desktop.ini b/public/Users/Public/Videos/desktop.ini index 970e2560..738427ec 100644 --- a/public/Users/Public/Videos/desktop.ini +++ b/public/Users/Public/Videos/desktop.ini @@ -1,2 +1,2 @@ [ShellClassInfo] -IconFile=/System/Icons/videos.webp +IconFile=/System/Icons/videos.avif diff --git a/public/Users/Public/desktop.ini b/public/Users/Public/desktop.ini index 98b415fe..f25872c6 100644 --- a/public/Users/Public/desktop.ini +++ b/public/Users/Public/desktop.ini @@ -1,2 +1,2 @@ [ShellClassInfo] -IconFile=/System/Icons/user.webp +IconFile=/System/Icons/user.avif diff --git a/scripts/preloadIcons.js b/scripts/preloadIcons.js index bd7b2c5f..661a8641 100644 --- a/scripts/preloadIcons.js +++ b/scripts/preloadIcons.js @@ -3,10 +3,12 @@ const { extname, join } = require("path"); const { parse } = require("ini"); const HOME = "/Users/Public"; +const DESKTOP_PATH = `${HOME}/Desktop`; const START_MENU_PATH = `${HOME}/Start Menu`; const ICON_PATH = "/System/Icons"; -const NEW_FOLDER_ICON = `${ICON_PATH}/new_folder.webp`; +const SHORTCUT_ICON = `${ICON_PATH}/shortcut.avif`; +const NEW_FOLDER_ICON = `${ICON_PATH}/new_folder.avif`; const getPublicDirectoryIcons = (directory) => { const baseDirectory = join("./public", directory); @@ -24,6 +26,11 @@ const getPublicDirectoryIcons = (directory) => { }, []); }; +writeFileSync( + "./public/.index/desktopIcons.json", + JSON.stringify([SHORTCUT_ICON, ...getPublicDirectoryIcons(DESKTOP_PATH)]) +); + writeFileSync( "./public/.index/startMenuIcons.json", JSON.stringify([NEW_FOLDER_ICON, ...getPublicDirectoryIcons(START_MENU_PATH)]) diff --git a/styles/common/Icon.tsx b/styles/common/Icon.tsx index d22ffa92..0b0e22e8 100644 --- a/styles/common/Icon.tsx +++ b/styles/common/Icon.tsx @@ -1,7 +1,6 @@ -import { basename, dirname, join } from "path"; import { memo, useEffect, useMemo, useState } from "react"; import styled from "styled-components"; -import { cleanUpBufferUrl } from "utils/functions"; +import { cleanUpBufferUrl, imageSrcs } from "utils/functions"; export type IconProps = { $displaySize?: number; @@ -48,19 +47,7 @@ const Icon: FC> = ( src.startsWith("https:") || src.startsWith("data:") || src.endsWith(".ico"); - const baseDirName = dirname(src); - const baseFileName = basename(src, ".webp"); - const imgSrc = (size: number, ratio: number, extension: string): string => - `${join( - baseDirName, - `${size * ratio}x${size * ratio}`, - `${baseFileName}${extension}` - )}${ratio > 1 ? ` ${ratio}x` : ""}`; const { $imgSize } = props; - const imgSrcs = (extension = ".webp"): string => - `${imgSrc($imgSize, 1, extension)}, - ${imgSrc($imgSize, 2, extension)}, - ${imgSrc($imgSize, 3, extension)}`; useEffect( () => () => { @@ -74,7 +61,7 @@ const Icon: FC> = ( ref={$imgRef} onLoad={() => setLoaded(true)} src={isStaticIcon ? src : undefined} - srcSet={!isStaticIcon ? imgSrcs(".png") : undefined} + srcSet={!isStaticIcon ? imageSrcs(src, $imgSize, ".png") : undefined} style={style} {...componentProps} /> @@ -84,8 +71,8 @@ const Icon: FC> = ( return ( - - + + {RenderedIcon} ); diff --git a/utils/constants.ts b/utils/constants.ts index ab12514a..587eee34 100644 --- a/utils/constants.ts +++ b/utils/constants.ts @@ -59,7 +59,7 @@ export const IMAGE_FILE_EXTENSIONS = new Set([ ".xbm", ]); -export const PHOTO_ICON = "/System/Icons/photo.webp"; +export const PHOTO_ICON = "/System/Icons/photo.avif"; export const INVALID_FILE_CHARACTERS = /["*/:<>?\\|]/g; @@ -215,19 +215,22 @@ export const USER_ICON_PATH = `${HOME}/Icons`; export const ICON_CACHE = `${USER_ICON_PATH}/Cache`; -export const SHORTCUT_ICON = `${ICON_PATH}/shortcut.webp`; +export const SHORTCUT_ICON = `${ICON_PATH}/shortcut.avif`; -export const FOLDER_ICON = `${ICON_PATH}/folder.webp`; +export const FOLDER_ICON = `${ICON_PATH}/folder.avif`; -export const FOLDER_BACK_ICON = `${ICON_PATH}/folder_back.webp`; +export const FOLDER_BACK_ICON = `${ICON_PATH}/folder_back.avif`; -export const FOLDER_FRONT_ICON = `${ICON_PATH}/folder_front.webp`; +export const FOLDER_FRONT_ICON = `${ICON_PATH}/folder_front.avif`; -export const COMPRESSED_FOLDER_ICON = `${ICON_PATH}/compressed.webp`; +export const COMPRESSED_FOLDER_ICON = `${ICON_PATH}/compressed.avif`; -export const MOUNTED_FOLDER_ICON = `${ICON_PATH}/mounted.webp`; +export const MOUNTED_FOLDER_ICON = `${ICON_PATH}/mounted.avif`; -export const NEW_FOLDER_ICON = `${ICON_PATH}/new_folder.webp`; +export const NEW_FOLDER_ICON = `${ICON_PATH}/new_folder.avif`; + +export const AVIF_TEST_IMAGE = + "data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A="; export const UNKNOWN_ICON = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAB0ElEQVR42u2ZVWLbQBiEp/K6DOpb+LF4ip47oCuULpAYH3uAlcbMNOZpm0lsizWz+/3CgEc9aiuFHz9/YYVIcjAAkODcYYDoTyPQHZse7m0E49tLkid/8rz4BuD7RgFIYpW+fvmMXStJEvz+/RuvXr1KG41mVhT5RiECRMUYsUuF0Nv18+fPcXp6ktbrjSzPhRBCDxxUpVKpG+Ls7DSt1eprhwjYWwAdJQD9EGftELV2iCiHCAQMAvT04sVznJ+fpdVqNcuj1hOBJj0wCvECFxcXaeWhIuEUYFADAGZCXF5dpg/3DxmA99YIZVmGRXr58lVqi1CMER8+fOh+pkUS5XIZd7d3ylEIViI5M7wCITqa1wOAtDVPKD1A45andC1ES/N6DZCuzKsIWZr3RoikMK4jZGleD2BsntDOA74tT0gIOZrXEfJmXiti24KleBi1M09SThBIU/P6mZiW5qEXMW3NUzuMGrc8NYRssSE0hFyZVxFyLVgdIcOW51oIWZqHfj9ga15+rOLb8lIRg47m9RoQ/R+eeb0GaGleR8i15XWEqL5VFIIJ87V5u70nvrm+AUF0/8nx4ZlxgOj+9KeTk+Oz8/rrYnIYBAoWeNSj9qwWS/T9vUU9j2EAAAAASUVORK5CYII="; diff --git a/utils/functions.ts b/utils/functions.ts index 4e1dd92f..1d173344 100644 --- a/utils/functions.ts +++ b/utils/functions.ts @@ -1,10 +1,14 @@ import type { Size } from "components/system/Window/RndWindow/useResizable"; import type { RelativePosition } from "contexts/process/types"; import type { Position } from "eruda"; -import { extname } from "path"; +import { basename, dirname, extname, join } from "path"; import type { HTMLAttributes } from "react"; import { useEffect } from "react"; -import { ONE_TIME_PASSIVE_EVENT, TASKBAR_HEIGHT } from "utils/constants"; +import { + AVIF_TEST_IMAGE, + ONE_TIME_PASSIVE_EVENT, + TASKBAR_HEIGHT, +} from "utils/constants"; export const GOOGLE_SEARCH_QUERY = "https://www.google.com/search?igu=1&q="; @@ -14,6 +18,73 @@ export const bufferToBlob = (buffer: Buffer, type?: string): Blob => export const bufferToUrl = (buffer: Buffer): string => URL.createObjectURL(bufferToBlob(buffer)); +export type ImageFormat = "avif" | "png" | "webp"; + +declare global { + interface Window { + IMAGE_FORMAT?: ImageFormat; + } +} + +export const detectImageFormat = (): Promise => + new Promise((resolve) => { + if (typeof window.IMAGE_FORMAT !== "undefined") { + resolve(window.IMAGE_FORMAT); + } else { + const image = new Image(); + + image.addEventListener( + "error", + () => { + try { + const supportsWebp = document + .createElement("canvas") + .toDataURL("image/webp", 0) + .startsWith("data:image/webp"); + + window.IMAGE_FORMAT = supportsWebp ? "webp" : "png"; + } catch { + window.IMAGE_FORMAT = "png"; + } finally { + resolve(window.IMAGE_FORMAT as ImageFormat); + } + }, + ONE_TIME_PASSIVE_EVENT + ); + image.addEventListener( + "load", + () => { + window.IMAGE_FORMAT = "avif"; + resolve(window.IMAGE_FORMAT); + }, + ONE_TIME_PASSIVE_EVENT + ); + + image.src = AVIF_TEST_IMAGE; + } + }); + +export const imageSrc = ( + imagePath: string, + size: number, + ratio: number, + extension: string +): string => + `${join( + dirname(imagePath), + `${size * ratio}x${size * ratio}`, + `${basename(imagePath, ".avif")}${extension}` + ).replace(/\\/g, "/")}${ratio > 1 ? ` ${ratio}x` : ""}`; + +export const imageSrcs = ( + imagePath: string, + size: number, + extension: string +): string => + `${imageSrc(imagePath, size, 1, extension)}, + ${imageSrc(imagePath, size, 2, extension)}, + ${imageSrc(imagePath, size, 3, extension)}`; + export const imageToBufferUrl = ( path: string, buffer: Buffer | string