refactor: once again move background utils, this time to api

This commit is contained in:
David Ralph
2024-03-02 22:46:28 +00:00
parent a049cb297d
commit 12248db893
17 changed files with 16 additions and 23 deletions

View File

@@ -1,15 +0,0 @@
const testImage =
'AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAAFCbWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAFBETmF2aWYAAAAADnBpdG0AAAAAAAEAAAAsaWxvYwAAAABEAAACAAEAAAABAAACRgAAABgAAgAAAAEAAAFqAAAA3AAAAEFpaW5mAAAAAAACAAAAGmluZmUCAAAAAAEAAGF2MDFDb2xvcgAAAAAZaW5mZQIAAAEAAgAARXhpZkV4aWYAAAAAGmlyZWYAAAAAAAAADmNkc2MAAgABAAEAAAB5aXBycAAAAFlpcGNvAAAAFGlzcGUAAAAAAAAAAQAAAAEAAAAQcGFzcAAAAAEAAAABAAAADGF2MUOBABwAAAAADnBpeGkAAAAAAQgAAAATY29scm5jbHgAAQANAAGAAAAAGGlwbWEAAAAAAAAAAQABBQECg4SFAAAA/G1kYXQAAAAASUkqAAgAAAAGABIBAwABAAAAAQAAABoBBQABAAAAVgAAABsBBQABAAAAXgAAACgBAwABAAAAAgAAADEBAgARAAAAZgAAAGmHBAABAAAAeAAAAAAAAAABAAAAAQAAAAEAAAABAAAAcGFpbnQubmV0IDQuMy4xMgAABQAAkAcABAAAADAyMzABoAMAAQAAAAEAAAACoAQAAQAAAAEAAAADoAQAAQAAAAEAAAAFoAQAAQAAALoAAAAAAAAAAgABAAIABAAAAFI5OAACAAcABAAAADAxMDAAAAAAEgAKBxgABpgIaA0yCxJABBEAEADG1FkX';
/**
* It creates a new image element, sets the source to a base64 encoded AVIF image, and then resolves
* true if the image loads successfully, or false if it doesn't
*/
export const supportsAVIF = () => {
new Promise((resolve) => {
const image = new Image();
image.src = `data:image/avif;base64,${testImage}`;
image.onload = () => resolve(true);
image.onerror = () => resolve(false);
});
};

View File

@@ -1,35 +0,0 @@
import offlineImages from 'utils/data/offline_images.json';
/**
* It gets a random photographer from the offlineImages.json file, then gets a random image from that
* photographer, and returns an object with the image's URL, type, and photoInfo.
* </code>
* @param type - 'background' or 'thumbnail'
* @returns An object with the following properties:
* url: A string that is the path to the image.
* type: A string that is the type of image.
* photoInfo: An object with the following properties:
* offline: A boolean that is true.
* credit: A string that is the name of the photographer.
*/
export function offlineBackground(type) {
const photographers = Object.keys(offlineImages);
const photographer = photographers[Math.floor(Math.random() * photographers.length)];
const randomImage =
offlineImages[photographer].photo[
Math.floor(Math.random() * offlineImages[photographer].photo.length)
];
const object = {
url: `src/assets/offline-images/${randomImage}.webp`,
type,
photoInfo: {
offline: true,
credit: photographer,
},
};
localStorage.setItem('currentBackground', JSON.stringify(object));
return object;
}

View File

@@ -1,46 +0,0 @@
/**
* It takes a gradient object and returns a style object
* @returns An object with two properties: type and style.
*/
export function gradientStyleBuilder({ type, angle, gradient }) {
// Note: Append the gradient for additional browser support.
const steps = gradient?.map((v) => `${v.colour} ${v.stop}%`);
const grad = `background: ${type}-gradient(${type === 'linear' ? `${angle}deg,` : ''}${steps})`;
return {
type: 'colour',
style: `background:${gradient[0]?.colour};${grad}`,
};
}
/**
* It gets the gradient settings from localStorage, parses it, and returns the gradient style.
* @returns A string.
*/
export function getGradient() {
const customBackgroundColour = localStorage.getItem('customBackgroundColour') || {
angle: '180',
gradient: [{ colour: '#ffb032', stop: 0 }],
type: 'linear',
};
let gradientSettings = '';
try {
gradientSettings = JSON.parse(customBackgroundColour);
} catch (e) {
const hexColorRegex = /#[0-9a-fA-F]{6}/s;
if (hexColorRegex.exec(customBackgroundColour)) {
// Colour used to be simply a hex colour or a NULL value before it was a JSON object. This automatically upgrades the hex colour value to the new standard. (NULL would not trigger an exception)
gradientSettings = {
type: 'linear',
angle: '180',
gradient: [{ colour: customBackgroundColour, stop: 0 }],
};
localStorage.setItem('customBackgroundColour', JSON.stringify(gradientSettings));
}
}
if (typeof gradientSettings === 'object' && gradientSettings !== null) {
return gradientStyleBuilder(gradientSettings);
}
}

View File

@@ -1,39 +0,0 @@
import rgbToHsv from './rgbToHsv';
import { setRGBA } from './setRgba';
const hexRegexp = /(^#{0,1}[0-9A-F]{6}$)|(^#{0,1}[0-9A-F]{3}$)|(^#{0,1}[0-9A-F]{8}$)/i;
const regexp = /([0-9A-F])([0-9A-F])([0-9A-F])/i;
/**
* It takes a hex color code and returns an object with the color's RGB and HSV values
* @param value - The hex value to convert to RGB.
* @returns An object with the properties red, green, blue, alpha, hue, saturation, and value.
*/
export default function hexToRgb(value) {
const valid = hexRegexp.test(value);
if (valid) {
if (value[0] === '#') {
value = value.slice(1, value.length);
}
if (value.length === 3) {
value = value.replace(regexp, '$1$1$2$2$3$3');
}
const red = parseInt(value.substr(0, 2), 16);
const green = parseInt(value.substr(2, 2), 16);
const blue = parseInt(value.substr(4, 2), 16);
const alpha = parseInt(value.substr(6, 2), 16) / 255;
const color = setRGBA(red, green, blue, alpha);
const hsv = rgbToHsv({ ...color });
return {
...color,
...hsv,
};
}
return false;
}

View File

@@ -1,17 +0,0 @@
import { getGradient, gradientStyleBuilder } from './getGradient';
import hexToRgb from './hexToRgb';
import rgbToHex from './rgbToHex';
import rgbToHsv from './rgbToHsv';
import { setRGBA, isValidRGBValue } from './setRgba';
export {
getGradient,
gradientStyleBuilder,
hexToRgb,
rgbToHex,
rgbToHsv,
setRGBA,
isValidRGBValue,
};

View File

@@ -1,27 +0,0 @@
/**
* It takes three numbers, converts them to hexadecimal, and returns a string of the three hexadecimal
* numbers concatenated together
* @param red - The red value of the color (0-255)
* @param green - 0
* @param blue - 0
* @returns a string of the hexadecimal value of the rgb values passed in.
*/
export default function rgbToHex(red, green, blue) {
let r16 = red.toString(16);
let g16 = green.toString(16);
let b16 = blue.toString(16);
if (red < 16) {
r16 = `0${r16}`;
}
if (green < 16) {
g16 = `0${g16}`;
}
if (blue < 16) {
b16 = `0${b16}`;
}
return r16 + g16 + b16;
}

View File

@@ -1,48 +0,0 @@
/**
* It converts RGB values to HSV values
* @returns An object with the hue, saturation, and value of the color.
* @param red - The red value of the color.
* @param green - 0-255
* @param blue - The blue value of the color.
*/
export default function rgbToHSv({ red, green, blue }) {
let rr, gg, bb, h, s;
const rabs = red / 255;
const gabs = green / 255;
const babs = blue / 255;
const v = Math.max(rabs, gabs, babs);
const diff = v - Math.min(rabs, gabs, babs);
const diffc = (c) => (v - c) / 6 / diff + 1 / 2;
if (diff === 0) {
h = 0;
s = 0;
} else {
s = diff / v;
rr = diffc(rabs);
gg = diffc(gabs);
bb = diffc(babs);
if (rabs === v) {
h = bb - gg;
} else if (gabs === v) {
h = 1 / 3 + rr - bb;
} else if (babs === v) {
h = 2 / 3 + gg - rr;
}
if (h < 0) {
h += 1;
} else if (h > 1) {
h -= 1;
}
}
return {
hue: Math.round(h * 360),
saturation: Math.round(s * 100),
value: Math.round(v * 100),
};
}

View File

@@ -1,35 +0,0 @@
/**
* It returns true if the value is a number, not NaN, and between 0 and 255.
* @param value - The value to check.
* @returns A function that takes a value and returns a boolean.
*/
export function isValidRGBValue(value) {
return typeof value === 'number' && Number.isNaN(value) === false && value >= 0 && value <= 255;
};
/**
* "If the red, green, and blue values are valid, return an object with the red, green, and blue
* values, and if the alpha value is valid, add it to the object."
*
* The function is a bit more complicated than that, but that's the gist of it
* @param red - The red value of the color.
* @param green - 0-255
* @param blue - The blue value of the color.
* @param alpha - The alpha value of the color.
* @returns An object with the properties red, green, blue, and alpha.
*/
export function setRGBA(red, green, blue, alpha) {
if (isValidRGBValue(red) && isValidRGBValue(green) && isValidRGBValue(blue)) {
const color = {
red: red | 0,
green: green | 0,
blue: blue | 0,
};
if (isValidRGBValue(alpha) === true) {
color.alpha = alpha | 0;
}
return color;
}
}

View File

@@ -1,6 +0,0 @@
import { supportsAVIF } from './avif';
import { offlineBackground } from './getOfflineImage';
import { randomColourStyleBuilder } from './randomColour';
import videoCheck from './videoCheck';
export { supportsAVIF, offlineBackground, randomColourStyleBuilder, videoCheck };

View File

@@ -1,34 +0,0 @@
/**
* It returns a random colour or random gradient as a style object
* @param type - The type of the style. This is used to determine which style builder to use.
* @returns An object with two properties: type and style.
*/
export function randomColourStyleBuilder(type) {
// randomColour based on https://stackoverflow.com/a/5092872
const randomColour = () =>
'#000000'.replace(/0/g, () => {
return (~~(Math.random() * 16)).toString(16);
});
let style = `background:${randomColour()};`;
if (type === 'random_gradient') {
const directions = [
'to right',
'to left',
'to bottom',
'to top',
'to bottom right',
'to bottom left',
'to top right',
'to top left',
];
style = `background:linear-gradient(${
directions[Math.floor(Math.random() * directions.length)]
}, ${randomColour()}, ${randomColour()});`;
}
return {
type: 'colour',
style,
};
}

View File

@@ -1,13 +0,0 @@
/**
* If the URL starts with `data:video/` or ends with `.mp4`, `.webm`, or `.ogg`, then it's a video.
* @param url - The URL of the file to be checked.
* @returns A function that takes a url and returns a boolean.
*/
export default function videoCheck(url) {
return (
url.startsWith('data:video/') ||
url.endsWith('.mp4') ||
url.endsWith('.webm') ||
url.endsWith('.ogg')
);
}

View File

@@ -1,32 +0,0 @@
{
"Ryan Hutton": {
"photo": [2]
},
"Francesco De Tommaso": {
"photo": [3]
},
"Andy Vu": {
"photo": [4]
},
"Kevin Kurek": {
"photo": [5]
},
"Frank Mckenna": {
"photo": [6]
},
"Yuriy Bogdanov": {
"photo": [7]
},
"Sergi Ferrete": {
"photo": [9]
},
"Marcin Czerniawski": {
"photo": [10]
},
"Thomas Lipke": {
"photo": [11]
},
"Pixabay": {
"photo": [1, 8, 12]
}
}