From ae61386216f72dfb94592254ee5e25e1dadafccd Mon Sep 17 00:00:00 2001 From: Angel Wang Date: Fri, 26 Jun 2026 16:12:25 -0600 Subject: [PATCH] feat(apply): initial implementation of multiple wallpapers --- src/apply/application.ts | 12 ++++++++++-- src/apply/index.ts | 25 +++++++++++++++++-------- src/utils.ts | 21 +++++++++++++++++++++ 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/src/apply/application.ts b/src/apply/application.ts index 49110e3..8aba1ca 100644 --- a/src/apply/application.ts +++ b/src/apply/application.ts @@ -12,6 +12,7 @@ export interface ApplicationConfig { lightnessRange: { night: number; dawn: number; noon: number } chromaRange: { start: number; end: number } targetSkyHue: number + numberOfWallpapers: number applyWallpaperCommand: string } @@ -28,6 +29,7 @@ export const defaultConfig: ApplicationConfig = { start: 0, end: 1, }, + numberOfWallpapers: 1, targetSkyHue: 264, applyWallpaperCommand: "hyprctl hyprpaper wallpaper , %s", } @@ -79,11 +81,11 @@ export async function getOpenMeteoData( } } -export function findMatchingImages(imagesData: ImageAnalysisData, targetColor: Colordx) { +export function findMatchingImages(imagesData: ImageAnalysisData, targetColor: Colordx, numberOfImages: number) { const matchingImages = [] let targetDelta = 0.06 - while (matchingImages.length == 0) { + while (matchingImages.length < numberOfImages) { console.debug(`Finding matching image with delta E ${targetDelta.toFixed(2)}...`) for (const image of imagesData.files) { if (targetColor.delta(image.colour) <= targetDelta) { @@ -95,3 +97,9 @@ export function findMatchingImages(imagesData: ImageAnalysisData, targetColor: C } return matchingImages } + +export function setWindowsWallpaper() { + const user32 = Deno.dlopen("user32.dll", { + SystemParametersInfoA: { parameters: ["u16", "u16", "pointer", "u16"], result: "void" } + }) +} \ No newline at end of file diff --git a/src/apply/index.ts b/src/apply/index.ts index 5ce1fe4..1913413 100644 --- a/src/apply/index.ts +++ b/src/apply/index.ts @@ -1,6 +1,6 @@ import { colordx } from "@colordx/core" import type { ImageAnalysisData } from "../analyze/analysis.ts" -import { applyConfigPath, cachePath, chalkDebug, easeOutQuint, loadConfig, map, mapEased } from "../utils.ts" +import { applyConfigPath, cachePath, chalkDebug, easeOutQuint, loadConfig, map, mapEased, shuffle } from "../utils.ts" import { type ApplicationConfig, defaultConfig, findMatchingImages, getOpenMeteoData } from "./application.ts" import * as SunCalc from "suncalc" import "zx/globals" @@ -60,6 +60,7 @@ const hueValue = Number(currentSunData.altitude) >= sunriseDegrees (x: number) => easeOutQuint(x), ) +console.log(hueValue) const chromaValue = map( 100 - Number(openMeteoData.cloudCover), // gotta invert this one 0, @@ -68,12 +69,13 @@ const chromaValue = map( config.chromaRange.end, ) -let lightnessValue = map( +let lightnessValue = mapEased( Number(openMeteoData.shortwaveRadiation), 0, 1000, config.lightnessRange.dawn, config.lightnessRange.noon, + (x) => Math.pow(x, 1 / 4) ) // if the current sun altitude is less than that of dawn/dusk @@ -93,16 +95,23 @@ const cacheFile = await fs.promises.readFile(`${cachePath}`, { const imagesData = JSON.parse(cacheFile) as ImageAnalysisData console.debug(chalkDebug(`Opened cache file ${cachePath}!`)) -const matchingImages = findMatchingImages(imagesData, targetColour) -const matchingImage = matchingImages[Math.floor(Math.random() * matchingImages.length)] -console.info( - `Found matching image ${matchingImage.path} with colour ${colordx(matchingImage.colour).toOklchString()}!`, +const matchingImages = shuffle(findMatchingImages(imagesData, targetColour, config.numberOfWallpapers)).slice( + 0, + config.numberOfWallpapers, ) +matchingImages.forEach((image) => + console.info( + `Found matching image ${image.path} with colour ${colordx(image.colour).toOklchString()}!`, + ) +) + +// TODO: implement setting more than one wallpaper. for ppl with multiple monitors + console.info(`Setting wallpaper...`) if (Deno.build.os != "windows") { - await $`eval ${config.applyWallpaperCommand.replace("%s", matchingImage.path)}` + await $`eval ${config.applyWallpaperCommand.replace("%s", matchingImages[0].path)}` } else { const command = ` $setwallpapersrc = @" @@ -122,7 +131,7 @@ public class Wallpaper { "@ Add-Type -TypeDefinition $setwallpapersrc -[Wallpaper]::SetWallpaper("${matchingImage.path}") +[Wallpaper]::SetWallpaper("${matchingImages[0].path}") ` usePowerShell() // await $`Write-Host ${command}` diff --git a/src/utils.ts b/src/utils.ts index 00296d3..820ea35 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -91,3 +91,24 @@ export function mapEased( ) { return func((number - min) / (max - min)) * (newMax - newMin) + newMin } + +// Fisher-Yates Shuffle +// deno-lint-ignore no-explicit-any +export function shuffle(array: any[]) { + let currentIndex = array.length + + // While there remain elements to shuffle... + while (currentIndex != 0) { + // Pick a remaining element... + const randomIndex = Math.floor(Math.random() * currentIndex) + currentIndex-- + + // And swap it with the current element. + [array[currentIndex], array[randomIndex]] = [ + array[randomIndex], + array[currentIndex], + ] + } + + return array +} -- 2.51.2