From 1be280c3baa580c5e475fc73257ec8aa996fc259 Mon Sep 17 00:00:00 2001 From: Dustin Brett Date: Wed, 8 Oct 2025 23:14:14 -0700 Subject: [PATCH] Add more wallpapers w/handler --- .../system/Desktop/Wallpapers/constants.ts | 13 ++- .../system/Desktop/Wallpapers/handlers.ts | 110 ++++++++++++++++++ components/system/Desktop/Wallpapers/types.ts | 23 +++- .../system/Desktop/Wallpapers/useWallpaper.ts | 69 +++-------- .../Files/FileManager/useFolderContextMenu.ts | 45 +++---- utils/functions.ts | 5 +- 6 files changed, 175 insertions(+), 90 deletions(-) create mode 100644 components/system/Desktop/Wallpapers/handlers.ts diff --git a/components/system/Desktop/Wallpapers/constants.ts b/components/system/Desktop/Wallpapers/constants.ts index 10565612..7b2c275d 100644 --- a/components/system/Desktop/Wallpapers/constants.ts +++ b/components/system/Desktop/Wallpapers/constants.ts @@ -63,13 +63,23 @@ export const REDUCED_MOTION_PERCENT = 0.1; export const WALLPAPER_MENU: WallpaperMenuItem[] = [ { + id: "ART_INSTITUTE_OF_CHICAGO", + name: "Art Institute of Chicago", + }, + { + hasAlt: false, id: "COASTAL_LANDSCAPE", name: "Coastal Landscape", }, { + hasAlt: false, id: "HEXELLS", name: "Hexells", }, + { + id: "LOREM_PICSUM", + name: "Lorem Picsum", + }, { id: "MATRIX 2D", name: "Matrix (2D)", @@ -81,13 +91,13 @@ export const WALLPAPER_MENU: WallpaperMenuItem[] = [ { id: "APOD", name: "NASA APOD", - startsWith: true, }, { id: "SLIDESHOW", name: "Picture Slideshow", }, { + hasAlt: false, id: "STABLE_DIFFUSION", name: "Stable Diffusion (beta)", requiresWebGPU: true, @@ -95,7 +105,6 @@ export const WALLPAPER_MENU: WallpaperMenuItem[] = [ { id: "VANTA", name: "Vanta Waves", - startsWith: true, }, ]; diff --git a/components/system/Desktop/Wallpapers/handlers.ts b/components/system/Desktop/Wallpapers/handlers.ts new file mode 100644 index 00000000..290aa040 --- /dev/null +++ b/components/system/Desktop/Wallpapers/handlers.ts @@ -0,0 +1,110 @@ +import { + type WallpaperHandler, + type ApodResponse, + type ArtInstituteOfChicagoResponse, +} from "components/system/Desktop/Wallpapers/types"; +import { type WallpaperFit } from "contexts/session/types"; +import { + jsonFetch, + viewWidth, + isYouTubeUrl, + getYouTubeUrlId, + viewHeight, +} from "utils/functions"; + +const API_URL = { + APOD: "https://api.nasa.gov/planetary/apod", + ART_INSTITUTE_OF_CHICAGO: "https://api.artic.edu/api/v1/search", +}; + +export const wallpaperHandler: Record = { + APOD: async ({ isAlt }) => { + const response = await jsonFetch( + `${API_URL.APOD}?${isAlt ? "count=1&" : ""}api_key=DEMO_KEY` + ); + const { hdurl, url } = (isAlt ? response[0] : response) as ApodResponse; + + let wallpaperUrl = ""; + let fallbackBackground = ""; + let newWallpaperFit = "" as WallpaperFit; + + if (hdurl || url) { + wallpaperUrl = (viewWidth() > 1024 ? hdurl : url) || url || ""; + newWallpaperFit = "fit"; + + if (isYouTubeUrl(wallpaperUrl)) { + const ytBaseUrl = `https://i.ytimg.com/vi/${getYouTubeUrlId( + wallpaperUrl + )}`; + + wallpaperUrl = `${ytBaseUrl}/maxresdefault.jpg`; + fallbackBackground = `${ytBaseUrl}/hqdefault.jpg`; + } else if (hdurl && url && hdurl !== url) { + fallbackBackground = wallpaperUrl === url ? hdurl : url; + } + } + + return { + fallbackBackground, + newWallpaperFit, + wallpaperUrl, + }; + }, + ART_INSTITUTE_OF_CHICAGO: async () => { + const requestPayload = { + boost: false, + fields: ["image_id"], + limit: 1, + query: { + function_score: { + boost_mode: "replace", + query: { + bool: { + filter: [ + { + term: { + is_public_domain: true, + }, + }, + { + exists: { + field: "image_id", + }, + }, + ], + }, + }, + random_score: { + field: "id", + seed: Date.now(), + }, + }, + }, + resources: "artworks", + }; + const response = (await jsonFetch(API_URL.ART_INSTITUTE_OF_CHICAGO, { + body: JSON.stringify(requestPayload), + headers: { + "Content-Type": "application/json", + }, + method: "POST", + })) as ArtInstituteOfChicagoResponse; + const imageUrl = (isMaxSize: boolean): string => + response?.data?.[0]?.image_id + ? `https://www.artic.edu/iiif/2/${response.data[0].image_id}/full/${ + isMaxSize ? "1686" : "843" + },/0/default.jpg` + : ""; + + return { + fallbackBackground: imageUrl(false), + newWallpaperFit: "fit", + wallpaperUrl: imageUrl(true), + }; + }, + LOREM_PICSUM: () => ({ + fallbackBackground: "", + newWallpaperFit: "fill", + wallpaperUrl: `https://picsum.photos/seed/${Date.now()}/${viewWidth()}/${viewHeight()}`, + }), +}; diff --git a/components/system/Desktop/Wallpapers/types.ts b/components/system/Desktop/Wallpapers/types.ts index 6a9ea7b8..eff80fe9 100644 --- a/components/system/Desktop/Wallpapers/types.ts +++ b/components/system/Desktop/Wallpapers/types.ts @@ -2,6 +2,7 @@ import { type StableDiffusionConfig } from "components/apps/StableDiffusion/type import { type VantaWavesConfig } from "components/system/Desktop/Wallpapers/vantaWaves/types"; import { type Size } from "components/system/Window/RndWindow/useResizable"; import type MatrixConfig from "components/system/Desktop/Wallpapers/Matrix/config"; +import { type WallpaperFit } from "contexts/session/types"; declare global { interface Window { @@ -30,10 +31,30 @@ export type OffscreenRenderProps = { }; export type WallpaperMenuItem = { + hasAlt?: boolean; id: string; name?: string; requiresWebGPU?: boolean; - startsWith?: boolean; }; export type WallpaperMessage = { message: string; type: string }; + +export type WallpaperData = { + fallbackBackground: string; + newWallpaperFit: WallpaperFit; + wallpaperUrl: string; +}; + +export type WallpaperHandler = (props: { + isAlt: boolean; +}) => Promise | WallpaperData; + +export type ApodResponse = { + date: string; + hdurl?: string; + url?: string; +}; + +export type ArtInstituteOfChicagoResponse = { + data: { image_id: string }[]; +}; diff --git a/components/system/Desktop/Wallpapers/useWallpaper.ts b/components/system/Desktop/Wallpapers/useWallpaper.ts index 075c5d45..f29635ad 100644 --- a/components/system/Desktop/Wallpapers/useWallpaper.ts +++ b/components/system/Desktop/Wallpapers/useWallpaper.ts @@ -1,6 +1,7 @@ import { join } from "path"; import { useTheme } from "styled-components"; import { useCallback, useEffect, useMemo, useRef } from "react"; +import { wallpaperHandler } from "components/system/Desktop/Wallpapers/handlers"; import { BASE_CANVAS_SELECTOR, BASE_VIDEO_SELECTOR, @@ -20,10 +21,8 @@ import { useFileSystem } from "contexts/fileSystem"; import { useSession } from "contexts/session"; import useWorker from "hooks/useWorker"; import { - DEFAULT_LOCALE, DEFAULT_WALLPAPER, IMAGE_FILE_EXTENSIONS, - MILLISECONDS_IN_DAY, MILLISECONDS_IN_MINUTE, NATIVE_IMAGE_FORMATS, PICTURES_FOLDER, @@ -38,13 +37,9 @@ import { cleanUpBufferUrl, createOffscreenCanvas, getExtension, - getYouTubeUrlId, isBeforeBg, - isYouTubeUrl, - jsonFetch, parseBgPosition, preloadImage, - viewWidth, } from "utils/functions"; const slideshowFiles: string[] = []; @@ -61,7 +56,7 @@ const useWallpaper = ( () => wallpaperImage.split(" "), [wallpaperImage] ); - const vantaWireframe = wallpaperImage === "VANTA WIREFRAME"; + const isAlt = wallpaperImage.endsWith(" ALT"); const wallpaperWorker = useWorker( sessionLoaded ? WALLPAPER_WORKERS[wallpaperName] : undefined ); @@ -107,7 +102,7 @@ const useWallpaper = ( config = { material: { options: { - wireframe: vantaWireframe || !isTopWindow, + wireframe: isAlt || !isTopWindow, }, }, waveSpeed: prefersReducedMotion ? REDUCED_MOTION_PERCENT : 1, @@ -115,8 +110,8 @@ const useWallpaper = ( } else if (wallpaperImage.startsWith("MATRIX")) { config = { animationSpeed: prefersReducedMotion ? REDUCED_MOTION_PERCENT : 1, - volumetric: wallpaperImage.endsWith("3D"), - ...(isTopWindow + volumetric: wallpaperImage.startsWith("MATRIX 3D"), + ...(isTopWindow && !isAlt ? {} : { fallSpeed: -0.09, @@ -226,10 +221,10 @@ const useWallpaper = ( [ desktopRef, exists, + isAlt, readFile, resetWallpaper, setWallpaper, - vantaWireframe, wallpaperImage, wallpaperName, wallpaperWorker, @@ -301,7 +296,7 @@ const useWallpaper = ( (await readFile(slideshowFilePath))?.toString() || "[]" ) as string[] ), - ].sort(() => Math.random() - 0.5) + ].sort(() => Math.random() - (isAlt ? 0.5 : -0.5)) ); } @@ -331,51 +326,15 @@ const useWallpaper = ( ); newWallpaperFit = "fill"; - } else if (wallpaperName === "APOD") { - // eslint-disable-next-line unicorn/no-unreadable-array-destructuring - const [, , currentDate] = wallpaperImage.split(" "); - const [month, , day, , year] = new Intl.DateTimeFormat(DEFAULT_LOCALE, { - day: "2-digit", - month: "2-digit", - timeZone: "US/Eastern", - year: "numeric", - }) - .formatToParts(Date.now()) - .map(({ value }) => value); - - if (currentDate === `${year}-${month}-${day}`) return; - + } else if (wallpaperHandler[wallpaperName]) { resetWallpaper(); - const { - date = "", - hdurl = "", - url = "", - } = await jsonFetch( - "https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY" - ); + const newWallpaper = await wallpaperHandler[wallpaperName]({ isAlt }); - if (hdurl || url) { - wallpaperUrl = ((viewWidth() > 1024 ? hdurl : url) || url) as string; - newWallpaperFit = "fit"; - - if (isYouTubeUrl(wallpaperUrl)) { - const ytBaseUrl = `https://i.ytimg.com/vi/${getYouTubeUrlId( - wallpaperUrl - )}`; - - wallpaperUrl = `${ytBaseUrl}/maxresdefault.jpg`; - fallbackBackground = `${ytBaseUrl}/hqdefault.jpg`; - } else if (hdurl && url && hdurl !== url) { - fallbackBackground = (wallpaperUrl === url ? hdurl : url) as string; - } - - const newWallpaperImage = `APOD ${wallpaperUrl} ${date as string}`; - - if (newWallpaperImage !== wallpaperImage) { - setWallpaper(newWallpaperImage, newWallpaperFit); - setTimeout(loadWallpaper, MILLISECONDS_IN_DAY); - } + if (newWallpaper) { + wallpaperUrl = newWallpaper.wallpaperUrl || ""; + fallbackBackground = newWallpaper.fallbackBackground || ""; + newWallpaperFit = newWallpaper.newWallpaperFit || newWallpaperFit; } } else if (await exists(wallpaperImage)) { resetWallpaper(); @@ -492,10 +451,10 @@ const useWallpaper = ( desktopRef, exists, getAllImages, + isAlt, loadWallpaper, readFile, resetWallpaper, - setWallpaper, updateFolder, wallpaperFit, wallpaperImage, diff --git a/components/system/Files/FileManager/useFolderContextMenu.ts b/components/system/Files/FileManager/useFolderContextMenu.ts index d731b90d..48c93a42 100644 --- a/components/system/Files/FileManager/useFolderContextMenu.ts +++ b/components/system/Files/FileManager/useFolderContextMenu.ts @@ -56,13 +56,10 @@ const updateSortBy = sortBy === value ? !isAscending : defaultIsAscending, ]; -const EASTER_EGG_CLICK_COUNT = 2; const CAPTURE_FPS = 30; const MIME_TYPE_VIDEO_WEBM = "video/webm"; const MIME_TYPE_VIDEO_MP4 = "video/mp4"; -let triggerEasterEggCountdown = EASTER_EGG_CLICK_COUNT; - let currentMediaStream: MediaStream | undefined; let currentMediaRecorder: MediaRecorder | undefined; @@ -96,26 +93,6 @@ const useFolderContextMenu = ( updateRecentFiles, wallpaperImage, } = useSession(); - const setWallpaper = useCallback( - (wallpaper: string) => { - if (wallpaper === "VANTA") { - triggerEasterEggCountdown -= 1; - - const triggerEasterEgg = triggerEasterEggCountdown === 0; - - setSessionWallpaper(`VANTA${triggerEasterEgg ? " WIREFRAME" : ""}`); - - if (triggerEasterEgg) { - triggerEasterEggCountdown = EASTER_EGG_CLICK_COUNT; - } - } else { - triggerEasterEggCountdown = EASTER_EGG_CLICK_COUNT; - - setSessionWallpaper(wallpaper); - } - }, - [setSessionWallpaper] - ); const { minimize, open } = useProcesses(); const updateSorting = useCallback( (value: SortBy | "", defaultIsAscending: boolean): void => { @@ -459,19 +436,27 @@ const useFolderContextMenu = ( menu: WALLPAPER_MENU.filter( ({ requiresWebGPU }) => !requiresWebGPU || hasWebGPU ).reduce( - (menu, item) => [ + (menu, { hasAlt = true, id, name }) => [ ...menu, { action: () => { if (isMusicVisualizationRunning) { stopGlobalMusicVisualization(); } - setWallpaper(item.id); + setSessionWallpaper( + `${id}${ + hasAlt && + wallpaperImage.startsWith(id) && + !wallpaperImage.endsWith(" ALT") + ? " ALT" + : "" + }` + ); }, - label: item.name || item.id, - toggle: item.startsWith - ? wallpaperImage.startsWith(item.id) - : wallpaperImage === item.id, + label: name || id, + toggle: hasAlt + ? wallpaperImage.startsWith(id) + : wallpaperImage === id, }, ], isMusicVisualizationRunning @@ -610,7 +595,7 @@ const useFolderContextMenu = ( processesRef, rootFs?.mntMap, setForegroundId, - setWallpaper, + setSessionWallpaper, sortBy, updateDesktopIconPositions, updateFolder, diff --git a/utils/functions.ts b/utils/functions.ts index bb365143..4d4cdfa8 100644 --- a/utils/functions.ts +++ b/utils/functions.ts @@ -1160,9 +1160,10 @@ export const getGifJs = async (): Promise => { }; export const jsonFetch = async ( - url: string + url: string, + options?: RequestInit ): Promise> => { - const response = await fetch(url, HIGH_PRIORITY_REQUEST); + const response = await fetch(url, { ...HIGH_PRIORITY_REQUEST, ...options }); const json = (await response.json()) as Record; return json || {};