From 063bc100942f7e3bd91402ab4448313e65ca5e38 Mon Sep 17 00:00:00 2001 From: Sean Edmunds Date: Mon, 21 Jul 2025 16:28:43 -0500 Subject: [PATCH] Added thumbnails and updated background pages --- package-lock.json | 54 +- package.json | 10 +- src/hooks/useCommonHooks.ts | 43 ++ .../Backgrounds/BackgroundLightbox.tsx | 38 + .../Theming/Backgrounds/BackgroundModal.tsx | 665 +++++++++--------- .../Theming/Backgrounds/DeleteBackground.tsx | 2 +- .../Theming/Backgrounds/EditBackground.tsx | 20 +- .../components/Theming/Themes/ThemeCard.tsx | 2 +- .../Theming/Themes/ThemeMiniCard.tsx | 2 +- .../components/Theming/Themes/ThemeModal.tsx | 153 +++- .../Theming/Themes/ThemeModalContent.tsx | 2 +- .../components/Theming/Themes/ThemeSelect.tsx | 4 +- 12 files changed, 603 insertions(+), 392 deletions(-) create mode 100644 src/pages/settings/components/Theming/Backgrounds/BackgroundLightbox.tsx diff --git a/package-lock.json b/package-lock.json index 7d646a3..fc14285 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,10 +9,10 @@ "version": "1.0.0", "dependencies": { "@hello-pangea/dnd": "^18.0.1", - "@mantine/core": "^8.1.3", - "@mantine/form": "^8.1.3", - "@mantine/hooks": "^8.1.3", - "@mantine/notifications": "^8.1.3", + "@mantine/core": "^8.2.1", + "@mantine/form": "^8.2.1", + "@mantine/hooks": "^8.2.1", + "@mantine/notifications": "^8.2.1", "@tanstack/react-query": "^5.83.0", "@tanstack/react-query-devtools": "^5.83.0", "@tanstack/react-query-persist-client": "^5.83.0", @@ -25,7 +25,7 @@ "recharts": "^3.1.0" }, "devDependencies": { - "@types/node": "^24.0.14", + "@types/node": "^24.0.15", "@types/react": "^19.1.8", "@types/react-dom": "^19.1.6", "@vitejs/plugin-react": "^4.7.0", @@ -930,9 +930,9 @@ } }, "node_modules/@mantine/core": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@mantine/core/-/core-8.1.3.tgz", - "integrity": "sha512-2WOPC8GSN3MApet0MccSn6LaXRhcP6SVtZnbuHoqJ/atrfK7kLE66ILr4OXov7JAj1ASJ4Xk0bOXmu5fBExAvQ==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@mantine/core/-/core-8.2.1.tgz", + "integrity": "sha512-KxvydotyFRdrRbqULUX2G35/GddPFju9XQUv/vdDWu1ytIWZViTguc+WSj1aBd0DtfRrSaofU5ezZISEXVrPBA==", "license": "MIT", "dependencies": { "@floating-ui/react": "^0.26.28", @@ -943,15 +943,15 @@ "type-fest": "^4.27.0" }, "peerDependencies": { - "@mantine/hooks": "8.1.3", + "@mantine/hooks": "8.2.1", "react": "^18.x || ^19.x", "react-dom": "^18.x || ^19.x" } }, "node_modules/@mantine/form": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@mantine/form/-/form-8.1.3.tgz", - "integrity": "sha512-OoSVv2cyjKRZ+C4Rw63VsnO3qjKGZHJkd6DSJTVRQHXfDr10hxmC5yXgxGKsxGQ+xFd4ZCdtzPUU2BoWbHfZAA==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@mantine/form/-/form-8.2.1.tgz", + "integrity": "sha512-XXGdO3IgTNcDl6lP7FIysEaH0rP6CfOGulxQA3ot+hHA8/JxmHWoWeoKOBE8I6QW7UYqaBxARxgBHLMcp8qASw==", "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.3", @@ -962,34 +962,34 @@ } }, "node_modules/@mantine/hooks": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-8.1.3.tgz", - "integrity": "sha512-yL4SbyYjrkmtIhscswajNz9RL0iO2+V8CMtOi0KISch2rPNvTAJNumFuZaXgj4UHeDc0JQYSmcZ+EW8NGm7xcQ==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@mantine/hooks/-/hooks-8.2.1.tgz", + "integrity": "sha512-gnRDk5FXCD9fa0AjlAj9otCsZL9QJzVrpYZk9KjOEoP5XR1TEE2F9/rGbajh1UVjPnD3jUlNLRJMH0YHTlA65A==", "license": "MIT", "peerDependencies": { "react": "^18.x || ^19.x" } }, "node_modules/@mantine/notifications": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-8.1.3.tgz", - "integrity": "sha512-Xy6f/l1yLTo77hz8X80sOuY+HW80e1rn8ucygx9TAexK5+XtyriOv26TQ3EJ6Ej5jlchtZRFEUJ4tJGRWjGCNg==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@mantine/notifications/-/notifications-8.2.1.tgz", + "integrity": "sha512-9s4oN0ruX7AqUghZIXEwx9/t+fHATe/kvn5O5Zum+MFoOH46p8k4ljNb6BBDKTtT3clRHx7KHTR7OrLWlDEjrw==", "license": "MIT", "dependencies": { - "@mantine/store": "8.1.3", + "@mantine/store": "8.2.1", "react-transition-group": "4.4.5" }, "peerDependencies": { - "@mantine/core": "8.1.3", - "@mantine/hooks": "8.1.3", + "@mantine/core": "8.2.1", + "@mantine/hooks": "8.2.1", "react": "^18.x || ^19.x", "react-dom": "^18.x || ^19.x" } }, "node_modules/@mantine/store": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/@mantine/store/-/store-8.1.3.tgz", - "integrity": "sha512-rO72LfSJqSNCwufqJxTWiHMyOR6sR3mqAcnBcw/f5aTvyOYoHZzlm4q4+TL8/2vYGRVsr9YM2Ez6HQ1vk/RR8g==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@mantine/store/-/store-8.2.1.tgz", + "integrity": "sha512-4DAVJcI5Sa8Zez/23DV4eipYbqRfw7r+UkuWczPFyhAU+BZdfIql1gFipojAlR0FpWbB8aL0F7wFKNKfkZ0YCQ==", "license": "MIT", "peerDependencies": { "react": "^18.x || ^19.x" @@ -1846,9 +1846,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "24.0.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.14.tgz", - "integrity": "sha512-4zXMWD91vBLGRtHK3YbIoFMia+1nqEz72coM42C5ETjnNCa/heoj7NT1G67iAfOqMmcfhuCZ4uNpyz8EjlAejw==", + "version": "24.0.15", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.15.tgz", + "integrity": "sha512-oaeTSbCef7U/z7rDeJA138xpG3NuKc64/rZ2qmUFkFJmnMsAPaluIifqyWd8hSSMxyP9oie3dLAqYPblag9KgA==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 5dd2347..d407c09 100644 --- a/package.json +++ b/package.json @@ -11,10 +11,10 @@ }, "dependencies": { "@hello-pangea/dnd": "^18.0.1", - "@mantine/core": "^8.1.3", - "@mantine/form": "^8.1.3", - "@mantine/hooks": "^8.1.3", - "@mantine/notifications": "^8.1.3", + "@mantine/core": "^8.2.1", + "@mantine/form": "^8.2.1", + "@mantine/hooks": "^8.2.1", + "@mantine/notifications": "^8.2.1", "@tanstack/react-query": "^5.83.0", "@tanstack/react-query-devtools": "^5.83.0", "@tanstack/react-query-persist-client": "^5.83.0", @@ -27,7 +27,7 @@ "recharts": "^3.1.0" }, "devDependencies": { - "@types/node": "^24.0.14", + "@types/node": "^24.0.15", "@types/react": "^19.1.8", "@types/react-dom": "^19.1.6", "@vitejs/plugin-react": "^4.7.0", diff --git a/src/hooks/useCommonHooks.ts b/src/hooks/useCommonHooks.ts index 471171f..66dc536 100644 --- a/src/hooks/useCommonHooks.ts +++ b/src/hooks/useCommonHooks.ts @@ -125,6 +125,48 @@ export function useCommonHooks() { return k; } + function getObjectDiff(original: any, current: any) { + const changes: any = {}; + + // Check current object's properties + for (const [key, value] of Object.entries(current)) { + if (!(key in original)) { + changes[key] = { + oldValue: undefined, + newValue: value, + }; + continue; + } + + const originalValue = original[key]; + const currentValue = value; + + // Handle different types of comparisons + if ( + originalValue !== currentValue && + String(originalValue) !== String(currentValue) && + JSON.stringify(originalValue) !== JSON.stringify(currentValue) + ) { + changes[key] = { + oldValue: originalValue, + newValue: currentValue, + }; + } + } + + // Check for removed properties + for (const key of Object.keys(original)) { + if (!(key in current)) { + changes[key] = { + oldValue: original[key], + newValue: undefined, + }; + } + } + + return Object.keys(changes).length === 0 ? null : changes; + } + return { isMobile, theme, @@ -132,6 +174,7 @@ export function useCommonHooks() { urlPattern, fixDigits, reorder, + getObjectDiff, handleThemeChange, handleDelete, themeName, diff --git a/src/pages/settings/components/Theming/Backgrounds/BackgroundLightbox.tsx b/src/pages/settings/components/Theming/Backgrounds/BackgroundLightbox.tsx new file mode 100644 index 0000000..2c061f2 --- /dev/null +++ b/src/pages/settings/components/Theming/Backgrounds/BackgroundLightbox.tsx @@ -0,0 +1,38 @@ +import { Group, Image, Modal, Text } from '@mantine/core'; + +export function BackgroundLightbox({ + opened, + close, + background, +}: { + opened: boolean; + close: () => void; + background: string; +}) { + return ( + + + {background} + + + + + + + + + + ); +} diff --git a/src/pages/settings/components/Theming/Backgrounds/BackgroundModal.tsx b/src/pages/settings/components/Theming/Backgrounds/BackgroundModal.tsx index 798027f..a844b0c 100644 --- a/src/pages/settings/components/Theming/Backgrounds/BackgroundModal.tsx +++ b/src/pages/settings/components/Theming/Backgrounds/BackgroundModal.tsx @@ -12,7 +12,7 @@ import { Text, TextInput, } from '@mantine/core'; -import { useDebouncedValue, useElementSize } from '@mantine/hooks'; +import { useDebouncedValue, useDisclosure, useElementSize } from '@mantine/hooks'; import { useCommonHooks } from 'hooks'; import { useFileUploadAPI } from 'hooks/useAPI'; import { useEffect, useState } from 'react'; @@ -24,6 +24,7 @@ import { scrollAreaClasses, textInputClasses, } from 'styles'; +import { BackgroundLightbox } from './BackgroundLightbox'; import { DeleteBackground } from './DeleteBackground'; import { EditBackground } from './EditBackground'; @@ -38,7 +39,10 @@ export function BackgroundModal({ backgroundList: string[]; inUseBackgrounds: string[]; }) { + const [opened, { open, close }] = useDisclosure(false); + const [lightboxName, setLightboxName] = useState(''); const { ref, width } = useElementSize(); + const [hovered, setHovered] = useState(''); const [background, setBackground] = useState(null); const [fileName, setFileName] = useState(''); const [newFileName, setNewFileName] = useState(''); @@ -64,326 +68,359 @@ export function BackgroundModal({ }, [debouncedSearch]); return ( - { - setBackground(null); - setFileName(''); - setNewFileName(''); - handleBackgroundModalClose(); - setConfirm(false); - setEditing(false); - }} - fullScreen={isMobile} - centered - keepMounted - > - - - - - - Manage Backgrounds - - - - - - - {!editing && !confirm && !adding && searchValue !== undefined && ( - - { - setIsLoading(true); - setSearchValue(event.target.value); - }} - style={{ - zIndex: 100, - paddingTop: 0, - }} - styles={ - theme.textShadowsEnabled - ? { - label: { boxShadow: '2px 2px var(--mantine-color-border-0)' }, - } - : undefined - } - rightSection={ - isLoading ? ( - - - - ) : ( - searchValue && ( - setSearchValue('')} - > - - - ) - ) - } - /> - - - )} - {confirm && ( - - )} - {editing && ( - - )} - {!editing && !confirm && !adding && ( - - - {backgroundList - .filter((background) => background !== 'None') - .filter( - (background) => - !debouncedSearch || - background - .toLocaleLowerCase() - .includes(debouncedSearch.toLocaleLowerCase()), - ) - .map((background) => ( - - - {background} - - - { - setFileName(background); - setEditing(true); - }} - > - - - { - setFileName(background); - setConfirm(true); - }} - > - - - - ))} - - - )} - {adding && ( - - - - - setNewFileName(e.target.value)} - pr={'xl'} - pl={0} - styles={{ - input: { - color: 'var(--mantine-color-primary-0)', - borderColor: 'var(--mantine-color-primary-0)', - }, - }} - /> - - + {opened && ( + + )} + { + setBackground(null); + setFileName(''); + setNewFileName(''); + handleBackgroundModalClose(); + setConfirm(false); + setEditing(false); + }} + fullScreen={isMobile} + centered + keepMounted={false} + > + + + + + + Manage Backgrounds + + + + + + + {!editing && !confirm && !adding && searchValue !== undefined && ( + + { + setIsLoading(true); + setSearchValue(event.target.value); + }} style={{ - aspectRatio: '16/9', - width: '35%', - backgroundSize: 'cover', - backgroundPosition: 'center', - backgroundRepeat: 'no-repeat', - backgroundColor: 'var(--mantine-color-search-0)', - padding: '2rem', - margin: '1rem', - marginRight: 0, + zIndex: 100, + paddingTop: 0, + }} + styles={ + theme.textShadowsEnabled + ? { + label: { boxShadow: '2px 2px var(--mantine-color-border-0)' }, + } + : undefined + } + rightSection={ + isLoading ? ( + + + + ) : ( + searchValue && ( + setSearchValue('')} + > + + + ) + ) + } + /> + - - + - - - - )} - - - - + }} + > + Cancel + + + + )} + + + + + ); } diff --git a/src/pages/settings/components/Theming/Backgrounds/DeleteBackground.tsx b/src/pages/settings/components/Theming/Backgrounds/DeleteBackground.tsx index 34ce7a0..a0ff898 100644 --- a/src/pages/settings/components/Theming/Backgrounds/DeleteBackground.tsx +++ b/src/pages/settings/components/Theming/Backgrounds/DeleteBackground.tsx @@ -46,7 +46,7 @@ export function DeleteBackground({ style={{ aspectRatio: '16/9', height: '100%', - backgroundImage: `url(../../api/backgroundImages/${fileName})`, + backgroundImage: `url(../../api/backgroundImages/thumbs/${fileName})`, backgroundSize: 'cover', backgroundPosition: 'center', backgroundRepeat: 'no-repeat', diff --git a/src/pages/settings/components/Theming/Backgrounds/EditBackground.tsx b/src/pages/settings/components/Theming/Backgrounds/EditBackground.tsx index 8291c18..95c780c 100644 --- a/src/pages/settings/components/Theming/Backgrounds/EditBackground.tsx +++ b/src/pages/settings/components/Theming/Backgrounds/EditBackground.tsx @@ -1,4 +1,4 @@ -import { Button, Card, Group, Stack, Text, TextInput } from '@mantine/core'; +import { Button, Group, Image, Stack, Text, TextInput } from '@mantine/core'; import { useCommonHooks, useMutationAPI } from 'hooks'; import { useState } from 'react'; import { textInputClasses } from 'styles'; @@ -27,7 +27,6 @@ export function EditBackground({ align='center' style={{ width: '100%', - height: '30rem', backgroundColor: 'var(--mantine-color-search-0)', padding: '1rem', borderRadius: '.5rem', @@ -42,7 +41,7 @@ export function EditBackground({ Updating the name will update the associated themes. )} - + - - + +