mirror of
https://github.com/streamyfin/streamyfin.git
synced 2026-01-15 23:59:08 +00:00
fix: design
This commit is contained in:
73
utils/atoms/primaryColor.ts
Normal file
73
utils/atoms/primaryColor.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { atom, useAtom } from "jotai";
|
||||
|
||||
interface ThemeColors {
|
||||
primary: string;
|
||||
secondary: string;
|
||||
average: string;
|
||||
text: string;
|
||||
}
|
||||
|
||||
const calculateTextColor = (backgroundColor: string): string => {
|
||||
// Convert hex to RGB
|
||||
const r = parseInt(backgroundColor.slice(1, 3), 16);
|
||||
const g = parseInt(backgroundColor.slice(3, 5), 16);
|
||||
const b = parseInt(backgroundColor.slice(5, 7), 16);
|
||||
|
||||
// Calculate perceived brightness
|
||||
// Using the formula: (R * 299 + G * 587 + B * 114) / 1000
|
||||
const brightness = (r * 299 + g * 587 + b * 114) / 1000;
|
||||
|
||||
// Calculate contrast ratio with white and black
|
||||
const contrastWithWhite = calculateContrastRatio([255, 255, 255], [r, g, b]);
|
||||
const contrastWithBlack = calculateContrastRatio([0, 0, 0], [r, g, b]);
|
||||
|
||||
// Use black text if the background is bright and has good contrast with black
|
||||
if (brightness > 180 && contrastWithBlack >= 4.5) {
|
||||
return "#000000";
|
||||
}
|
||||
|
||||
// Otherwise, use white text
|
||||
return "#FFFFFF";
|
||||
};
|
||||
|
||||
// Helper function to calculate contrast ratio
|
||||
const calculateContrastRatio = (rgb1: number[], rgb2: number[]): number => {
|
||||
const l1 = calculateRelativeLuminance(rgb1);
|
||||
const l2 = calculateRelativeLuminance(rgb2);
|
||||
const lighter = Math.max(l1, l2);
|
||||
const darker = Math.min(l1, l2);
|
||||
return (lighter + 0.05) / (darker + 0.05);
|
||||
};
|
||||
|
||||
// Helper function to calculate relative luminance
|
||||
const calculateRelativeLuminance = (rgb: number[]): number => {
|
||||
const [r, g, b] = rgb.map((c) => {
|
||||
c /= 255;
|
||||
return c <= 0.03928 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
||||
});
|
||||
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
||||
};
|
||||
|
||||
const baseThemeColorAtom = atom<ThemeColors>({
|
||||
primary: "#FFFFFF",
|
||||
secondary: "#000000",
|
||||
average: "#888888",
|
||||
text: "#000000",
|
||||
});
|
||||
|
||||
export const itemThemeColorAtom = atom(
|
||||
(get) => get(baseThemeColorAtom),
|
||||
(get, set, update: Partial<ThemeColors>) => {
|
||||
const currentColors = get(baseThemeColorAtom);
|
||||
const newColors = { ...currentColors, ...update };
|
||||
|
||||
// Recalculate text color if primary color changes
|
||||
if (update.primary) {
|
||||
newColors.text = calculateTextColor(update.primary);
|
||||
}
|
||||
|
||||
set(baseThemeColorAtom, newColors);
|
||||
}
|
||||
);
|
||||
|
||||
export const useItemThemeColor = () => useAtom(itemThemeColorAtom);
|
||||
@@ -34,7 +34,6 @@ export const getStreamUrl = async ({
|
||||
mediaSourceId?: string | null;
|
||||
}) => {
|
||||
if (!api || !userId || !item?.Id || !mediaSourceId) {
|
||||
console.error("Missing required parameters");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ export const postCapabilities = async ({
|
||||
sessionId,
|
||||
}: PostCapabilitiesParams): Promise<AxiosResponse> => {
|
||||
if (!api || !itemId || !sessionId) {
|
||||
throw new Error("Missing required parameters");
|
||||
throw new Error("Missing parameters for marking item as not played");
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user