mirror of
https://github.com/Stef-00012/Zipline-Android-App.git
synced 2025-05-10 18:05:52 +02:00
159 lines
4.7 KiB
TypeScript
159 lines
4.7 KiB
TypeScript
import { isLightColor, rgbaToHex, toRgba } from "@/functions/color";
|
|
import mimetypesJSON from "@/assets/mimetypes.json";
|
|
import type { Mimetypes } from "@/types/mimetypes";
|
|
import { namedColors } from "@/constants/colors";
|
|
import * as FileSystem from "expo-file-system";
|
|
import ms from "enhanced-ms";
|
|
import bytes from "bytes";
|
|
|
|
const mimetypes = mimetypesJSON as Mimetypes;
|
|
|
|
export function guessMimetype(
|
|
mimetype: keyof Mimetypes,
|
|
): Mimetypes[keyof Mimetypes] {
|
|
if (!mimetype) return "so";
|
|
|
|
const mime = mimetypes[mimetype];
|
|
if (!mime) return "so";
|
|
|
|
return mime;
|
|
}
|
|
|
|
export function guessExtension(
|
|
mimetype: Mimetypes[keyof Mimetypes],
|
|
): keyof Mimetypes {
|
|
if (!mimetype) return "application/octet-stream";
|
|
|
|
const mime = Object.entries(mimetypes).find(
|
|
([key, value]) => value === mimetype,
|
|
) as [keyof Mimetypes, Mimetypes[keyof Mimetypes]] | undefined;
|
|
if (!mime) return "application/octet-stream";
|
|
|
|
return mime[0];
|
|
}
|
|
|
|
export async function getFileDataURI(filePath: string): Promise<string | null> {
|
|
const base64Data = await FileSystem.readAsStringAsync(filePath, {
|
|
encoding: FileSystem.EncodingType.Base64,
|
|
});
|
|
|
|
const extension = filePath.split(".").pop();
|
|
|
|
const mimetype = guessExtension(extension as Mimetypes[keyof Mimetypes]);
|
|
|
|
const dataURI = `data:${mimetype};base64,${base64Data}`;
|
|
|
|
return dataURI;
|
|
}
|
|
|
|
export function timeDifference(currentDate: Date, targetDate: Date) {
|
|
const msPerMinute = 60 * 1000;
|
|
const msPerHour = msPerMinute * 60;
|
|
const msPerDay = msPerHour * 24;
|
|
const msPerMonth = msPerDay * 30;
|
|
const msPerYear = msPerDay * 365;
|
|
|
|
const elapsed = targetDate.getTime() - currentDate.getTime();
|
|
const isFuture = elapsed > 0;
|
|
|
|
const absElapsed = Math.abs(elapsed);
|
|
|
|
if (absElapsed < msPerMinute) {
|
|
const difference = Math.round(absElapsed / 1000);
|
|
return `${isFuture ? "in " : ""}${difference} second${difference !== 1 ? "s" : ""}${isFuture ? "" : " ago"}`;
|
|
}
|
|
|
|
if (absElapsed < msPerHour) {
|
|
const difference = Math.round(absElapsed / msPerMinute);
|
|
return `${isFuture ? "in " : ""}${difference} minute${difference !== 1 ? "s" : ""}${isFuture ? "" : " ago"}`;
|
|
}
|
|
|
|
if (absElapsed < msPerDay) {
|
|
const difference = Math.round(absElapsed / msPerHour);
|
|
return `${isFuture ? "in " : ""}${difference} hour${difference !== 1 ? "s" : ""}${isFuture ? "" : " ago"}`;
|
|
}
|
|
|
|
if (absElapsed < msPerMonth) {
|
|
const difference = Math.round(absElapsed / msPerDay);
|
|
return `${isFuture ? "in " : ""}${difference} day${difference !== 1 ? "s" : ""}${isFuture ? "" : " ago"}`;
|
|
}
|
|
|
|
if (absElapsed < msPerYear) {
|
|
const difference = Math.round(absElapsed / msPerMonth);
|
|
return `${isFuture ? "in " : ""}${difference} month${difference !== 1 ? "s" : ""}${isFuture ? "" : " ago"}`;
|
|
}
|
|
|
|
const difference = Math.round(absElapsed / msPerYear);
|
|
return `${isFuture ? "in " : ""}${difference} year${difference !== 1 ? "s" : ""}${isFuture ? "" : " ago"}`;
|
|
}
|
|
|
|
export function colorHash(str: string) {
|
|
let hash = 0;
|
|
for (let i = 0; i < str.length; i++) {
|
|
hash = str.charCodeAt(i) + ((hash << 5) - hash);
|
|
}
|
|
|
|
let color = "#";
|
|
for (let i = 0; i < 3; i++) {
|
|
const value = (hash >> (i * 8)) & 0xff;
|
|
color += `00${value.toString(16)}`.substr(-2);
|
|
}
|
|
|
|
return color;
|
|
}
|
|
|
|
export function convertToBytes(
|
|
value: string | number,
|
|
options?: bytes.BytesOptions,
|
|
): string | null {
|
|
if (typeof value === "number") return bytes(value, options);
|
|
|
|
if (/^\d+(\.\d+)?$/.test(value)) {
|
|
return bytes(Number.parseFloat(value), options);
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
export function convertToTime(
|
|
value: string | number,
|
|
// biome-ignore lint/suspicious/noExplicitAny: enhanced-ms does not export the FormatOptions interface
|
|
options?: any,
|
|
): string | null {
|
|
if (typeof value === "number") return ms(value);
|
|
|
|
if (/^\d+(\.\d+)?$/.test(value)) {
|
|
return ms(Number.parseFloat(value), options);
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
export function getRippleColor(color: string, fraction = 0.4) {
|
|
let hexColor = color;
|
|
|
|
if (hexColor in namedColors)
|
|
hexColor = namedColors[hexColor as keyof typeof namedColors];
|
|
|
|
if (!hexColor.startsWith("#")) return color;
|
|
|
|
const { r, g, b } = toRgba(hexColor);
|
|
const lightColor = isLightColor(hexColor);
|
|
|
|
if (lightColor) {
|
|
const newRed = Math.max(0, Math.floor(r * (1 - fraction)));
|
|
const newGreen = Math.max(0, Math.floor(g * (1 - fraction)));
|
|
const newBlue = Math.max(0, Math.floor(b * (1 - fraction)));
|
|
|
|
return rgbaToHex(newRed, newGreen, newBlue);
|
|
}
|
|
|
|
const newRed = Math.min(255, Math.floor(r + (255 - r) * fraction));
|
|
const newGreen = Math.min(255, Math.floor(g + (255 - g) * fraction));
|
|
const newBlue = Math.min(255, Math.floor(b + (255 - b) * fraction));
|
|
|
|
return rgbaToHex(newRed, newGreen, newBlue);
|
|
}
|
|
export function getMetricsDifference(first: number, last: number): number {
|
|
return Math.round(((first - last) / last) * 100) || 0;
|
|
}
|