diff --git a/client/app/components/ActivityGrid.tsx b/client/app/components/ActivityGrid.tsx index 966b4b5..9628df6 100644 --- a/client/app/components/ActivityGrid.tsx +++ b/client/app/components/ActivityGrid.tsx @@ -1,191 +1,197 @@ -import { useQuery } from "@tanstack/react-query" -import { getActivity, type getActivityArgs, type ListenActivityItem } from "api/api" -import Popup from "./Popup" -import { useState } from "react" -import { useTheme } from "~/hooks/useTheme" -import ActivityOptsSelector from "./ActivityOptsSelector" -import type { Theme } from "~/styles/themes.css" - +import { useQuery } from "@tanstack/react-query"; +import { + getActivity, + type getActivityArgs, + type ListenActivityItem, +} from "api/api"; +import Popup from "./Popup"; +import { useState } from "react"; +import { useTheme } from "~/hooks/useTheme"; +import ActivityOptsSelector from "./ActivityOptsSelector"; +import type { Theme } from "~/styles/themes.css"; function getPrimaryColor(theme: Theme): string { - const value = theme.primary; - const rgbMatch = value.match(/^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/); - if (rgbMatch) { - const [, r, g, b] = rgbMatch.map(Number); - return ( - '#' + - [r, g, b] - .map((n) => n.toString(16).padStart(2, '0')) - .join('') - ); - } - - return value; + const value = theme.primary; + const rgbMatch = value.match( + /^rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/ + ); + if (rgbMatch) { + const [, r, g, b] = rgbMatch.map(Number); + return "#" + [r, g, b].map((n) => n.toString(16).padStart(2, "0")).join(""); + } + + return value; } interface Props { - step?: string - range?: number - month?: number - year?: number - artistId?: number - albumId?: number - trackId?: number - configurable?: boolean - autoAdjust?: boolean + step?: string; + range?: number; + month?: number; + year?: number; + artistId?: number; + albumId?: number; + trackId?: number; + configurable?: boolean; + autoAdjust?: boolean; } export default function ActivityGrid({ - step = 'day', - range = 182, - month = 0, - year = 0, - artistId = 0, - albumId = 0, - trackId = 0, - configurable = false, - }: Props) { - - const [stepState, setStep] = useState(step) - const [rangeState, setRange] = useState(range) - - const { isPending, isError, data, error } = useQuery({ - queryKey: [ - 'listen-activity', - { - step: stepState, - range: rangeState, - month: month, - year: year, - artist_id: artistId, - album_id: albumId, - track_id: trackId - }, - ], - queryFn: ({ queryKey }) => getActivity(queryKey[1] as getActivityArgs), - }); - - - const { theme, themeName } = useTheme(); - const color = getPrimaryColor(theme); - - - if (isPending) { - return ( -
Loading...
-Loading...
+Error:{error.message}
; + + // from https://css-tricks.com/snippets/javascript/lighten-darken-color/ + function LightenDarkenColor(hex: string, lum: number) { + // validate hex string + hex = String(hex).replace(/[^0-9a-f]/gi, ""); + if (hex.length < 6) { + hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; } - if (isError) returnError:{error.message}
- - // from https://css-tricks.com/snippets/javascript/lighten-darken-color/ - function LightenDarkenColor(hex: string, lum: number) { - // validate hex string - hex = String(hex).replace(/[^0-9a-f]/gi, ''); - if (hex.length < 6) { - hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2]; - } - lum = lum || 0; - - // convert to decimal and change luminosity - var rgb = "#", c, i; - for (i = 0; i < 3; i++) { - c = parseInt(hex.substring(i*2,(i*2)+2), 16); - c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16); - rgb += ("00"+c).substring(c.length); - } - - return rgb; + lum = lum || 0; + + // convert to decimal and change luminosity + var rgb = "#", + c, + i; + for (i = 0; i < 3; i++) { + c = parseInt(hex.substring(i * 2, i * 2 + 2), 16); + c = Math.round(Math.min(Math.max(0, c + c * lum), 255)).toString(16); + rgb += ("00" + c).substring(c.length); } - const getDarkenAmount = (v: number, t: number): number => { - - // really ugly way to just check if this is for all items and not a specific item. - // is it jsut better to just pass the target in as a var? probably. - const adjustment = artistId == albumId && albumId == trackId && trackId == 0 ? 10 : 1 - - // automatically adjust the target value based on step - // the smartest way to do this would be to have the api return the - // highest value in the range. too bad im not smart - switch (stepState) { - case 'day': - t = 10 * adjustment - break; - case 'week': - t = 20 * adjustment - break; - case 'month': - t = 50 * adjustment - break; - case 'year': - t = 100 * adjustment - break; - } - - v = Math.min(v, t) - if (themeName === "pearl") { - // special case for the only light theme lol - // could be generalized by pragmatically comparing the - // lightness of the bg vs the primary but eh - return ((t-v) / t) - } else { - return ((v-t) / t) * .8 - } + return rgb; + } + + const getDarkenAmount = (v: number, t: number): number => { + // really ugly way to just check if this is for all items and not a specific item. + // is it jsut better to just pass the target in as a var? probably. + const adjustment = + artistId == albumId && albumId == trackId && trackId == 0 ? 10 : 1; + + // automatically adjust the target value based on step + // the smartest way to do this would be to have the api return the + // highest value in the range. too bad im not smart + switch (stepState) { + case "day": + t = 10 * adjustment; + break; + case "week": + t = 20 * adjustment; + break; + case "month": + t = 50 * adjustment; + break; + case "year": + t = 100 * adjustment; + break; } - const CHUNK_SIZE = 26 * 7; - const chunks = []; - - for (let i = 0; i < data.length; i += CHUNK_SIZE) { - chunks.push(data.slice(i, i + CHUNK_SIZE)); + v = Math.min(v, t); + if (themeName === "pearl") { + // special case for the only light theme lol + // could be generalized by pragmatically comparing the + // lightness of the bg vs the primary but eh + return (t - v) / t; + } else { + return ((v - t) / t) * 0.8; } - - return ( -