Add more wallpapers w/handler
Some checks are pending
Tests / tests (push) Waiting to run

This commit is contained in:
Dustin Brett 2025-10-08 23:14:14 -07:00
parent 5c12a3aa2e
commit 1be280c3ba
6 changed files with 175 additions and 90 deletions

View File

@ -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,
},
];

View File

@ -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<string, WallpaperHandler> = {
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()}`,
}),
};

View File

@ -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> | WallpaperData;
export type ApodResponse = {
date: string;
hdurl?: string;
url?: string;
};
export type ArtInstituteOfChicagoResponse = {
data: { image_id: string }[];
};

View File

@ -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<void>(
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,

View File

@ -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<MenuItem[]>(
(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,

View File

@ -1160,9 +1160,10 @@ export const getGifJs = async (): Promise<GIFWithWorkers> => {
};
export const jsonFetch = async (
url: string
url: string,
options?: RequestInit
): Promise<Record<string, unknown>> => {
const response = await fetch(url, HIGH_PRIORITY_REQUEST);
const response = await fetch(url, { ...HIGH_PRIORITY_REQUEST, ...options });
const json = (await response.json()) as Record<string, unknown>;
return json || {};