Added thumbnails and updated background pages

This commit is contained in:
Sean Edmunds
2025-07-21 16:28:43 -05:00
parent 2a53d9f16a
commit 063bc10094
12 changed files with 603 additions and 392 deletions

View File

@@ -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 (
<Modal.Root opened={opened} onClose={close} size={'auto'} centered zIndex={250}>
<Group
px={'1rem'}
onClick={close}
w={'100%'}
pos={'absolute'}
top={'1rem'}
justify='space-between'
style={{ zIndex: 251 }}
>
<Text style={{ color: 'var(--mantine-color-primary-0)' }}>{background}</Text>
<Modal.CloseButton c={'red'} bg={'none'} />
</Group>
<Modal.Overlay opacity={0.1} />
<Modal.Content>
<Modal.Body p={'1rem'}>
<Image
style={{ cursor: 'zoom-out' }}
onClick={close}
src={`../../api/backgroundImages/${background}`}
/>
</Modal.Body>
</Modal.Content>
</Modal.Root>
);
}

View File

@@ -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<string>('');
const { ref, width } = useElementSize();
const [hovered, setHovered] = useState<string>('');
const [background, setBackground] = useState<File | null>(null);
const [fileName, setFileName] = useState<string>('');
const [newFileName, setNewFileName] = useState<string>('');
@@ -64,326 +68,359 @@ export function BackgroundModal({
}, [debouncedSearch]);
return (
<Modal.Root
size={'75%'}
className={modalClasses.editThemeModal}
classNames={modalClasses}
opened={backgroundModalOpened}
onClose={() => {
setBackground(null);
setFileName('');
setNewFileName('');
handleBackgroundModalClose();
setConfirm(false);
setEditing(false);
}}
fullScreen={isMobile}
centered
keepMounted
>
<Modal.Overlay />
<Modal.Content>
<Modal.Header style={{ justifyContent: 'center' }}>
<Group pos={'absolute'}>
<Text fw={600} fz={'1.5rem'} c={'var(--mantine-color-primary-0)'}>
Manage Backgrounds
</Text>
</Group>
<Modal.CloseButton />
</Modal.Header>
<Modal.Body p={'1rem'}>
<Stack align='center' w={'100%'}>
{!editing && !confirm && !adding && searchValue !== undefined && (
<Group w={'100%'} justify='center'>
<TextInput
w={'50%'}
className={textInputClasses.default}
classNames={textInputClasses}
autoFocus={!isMobile}
placeholder={'Search...'}
value={searchValue}
onInput={(event: any) => {
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 ? (
<ActionIcon
className={actionIconClasses.loadingSpinner}
classNames={actionIconClasses}
>
<FiLoader />
</ActionIcon>
) : (
searchValue && (
<ActionIcon
className={actionIconClasses.settingsTooltip}
classNames={actionIconClasses}
onClick={() => setSearchValue('')}
>
<FiX />
</ActionIcon>
)
)
}
/>
<Button
className={buttonClasses.newItemButton}
classNames={buttonClasses}
onClick={() => {
setAdding(true);
}}
>
<FiPlus />
</Button>
</Group>
)}
{confirm && (
<DeleteBackground
fileName={fileName}
setFileName={setFileName}
inUseBackgrounds={inUseBackgrounds}
setBackground={setBackground}
setNewFileName={setNewFileName}
setConfirm={setConfirm}
/>
)}
{editing && (
<EditBackground
fileName={fileName}
setFileName={setFileName}
inUseBackgrounds={inUseBackgrounds}
setBackground={setBackground}
setNewFileName={setNewFileName}
setEditing={setEditing}
/>
)}
{!editing && !confirm && !adding && (
<ScrollArea
className={scrollAreaClasses.default}
classNames={scrollAreaClasses}
type={'always'}
style={{
width: '100%',
height: '30rem',
backgroundColor: 'var(--mantine-color-search-0)',
padding: '1rem',
borderRadius: '.5rem',
backgroundFilter: 'blur(5px)',
}}
>
<SimpleGrid w={'100%'} cols={3} p={'.75rem'}>
{backgroundList
.filter((background) => background !== 'None')
.filter(
(background) =>
!debouncedSearch ||
background
.toLocaleLowerCase()
.includes(debouncedSearch.toLocaleLowerCase()),
)
.map((background) => (
<Group key={background} display={'flex'} pos={'relative'}>
<Text
style={{
color: 'var(--mantine-color-primary-0)',
backgroundColor: 'var(--mantine-color-accent-0)',
padding: '.25rem',
borderRadius: '.5rem',
position: 'absolute',
top: '-.5rem',
left: 0,
zIndex: 3,
boxShadow: '2px -2px var(--mantine-color-primary-0)',
textOverflow: 'ellipsis',
overflow: 'hidden',
whiteSpace: 'nowrap',
maxWidth: width,
}}
>
{background}
</Text>
<Card
ref={ref}
style={{
aspectRatio: '16/9',
width: '100%',
backgroundImage: `url(../../api/backgroundImages/${background})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
padding: '2rem',
margin: '1rem',
}}
/>
<ActionIcon
style={{
position: 'absolute',
bottom: '.5rem',
right: '2.5rem',
zIndex: 3,
}}
onClick={() => {
setFileName(background);
setEditing(true);
}}
>
<FiEdit />
</ActionIcon>
<ActionIcon
color='var(--mantine-color-red-6)'
style={{
position: 'absolute',
bottom: '.5rem',
right: '.5rem',
zIndex: 3,
}}
onClick={() => {
setFileName(background);
setConfirm(true);
}}
>
<FiTrash color='black' />
</ActionIcon>
</Group>
))}
</SimpleGrid>
</ScrollArea>
)}
{adding && (
<Stack
display={'flex'}
pos={'relative'}
w={'100%'}
align={'center'}
justify='space-between'
p={16}
>
<Group gap={0}>
<Stack gap={0} w={'60%'}>
<FileInput
clearable
accept='image/png,image/jpeg'
value={background}
onChange={handleFileUpload}
label={'Upload Background'}
placeholder={'Select...'}
error={err && 'Please upload a background'}
description={
'Max size: 50MB for upload. Images are resized to 300kb after upload.'
}
pr={'xl'}
pl={0}
styles={{
input: {
color: 'var(--mantine-color-primary-0)',
borderColor: 'var(--mantine-color-primary-0)',
},
placeholder: {
color: 'var(--mantine-color-accent-0)',
},
}}
/>
<TextInput
label={'File Name'}
placeholder={fileName}
value={newFileName}
onChange={(e) => setNewFileName(e.target.value)}
pr={'xl'}
pl={0}
styles={{
input: {
color: 'var(--mantine-color-primary-0)',
borderColor: 'var(--mantine-color-primary-0)',
},
}}
/>
</Stack>
<Card
<>
{opened && (
<BackgroundLightbox opened={opened} close={close} background={lightboxName} />
)}
<Modal.Root
size={'75%'}
className={modalClasses.editThemeModal}
classNames={modalClasses}
opened={backgroundModalOpened}
onClose={() => {
setBackground(null);
setFileName('');
setNewFileName('');
handleBackgroundModalClose();
setConfirm(false);
setEditing(false);
}}
fullScreen={isMobile}
centered
keepMounted={false}
>
<Modal.Overlay />
<Modal.Content>
<Modal.Header style={{ justifyContent: 'center' }}>
<Group pos={'absolute'}>
<Text fw={600} fz={'1.5rem'} c={'var(--mantine-color-background-0)'}>
Manage Backgrounds
</Text>
</Group>
<Modal.CloseButton />
</Modal.Header>
<Modal.Body p={'1rem'}>
<Stack align='center' w={'100%'}>
{!editing && !confirm && !adding && searchValue !== undefined && (
<Group w={'100%'} justify='center'>
<TextInput
w={'50%'}
className={textInputClasses.default}
classNames={textInputClasses}
autoFocus={!isMobile}
placeholder={'Search...'}
value={searchValue}
onInput={(event: any) => {
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 ? (
<ActionIcon
className={actionIconClasses.loadingSpinner}
classNames={actionIconClasses}
>
<FiLoader />
</ActionIcon>
) : (
searchValue && (
<ActionIcon
className={actionIconClasses.settingsTooltip}
classNames={actionIconClasses}
onClick={() => setSearchValue('')}
>
<FiX />
</ActionIcon>
)
)
}
/>
<Button
className={buttonClasses.newItemButton}
classNames={buttonClasses}
onClick={() => {
setAdding(true);
}}
>
{background ? (
<Image
src={URL.createObjectURL(background)}
w={'100%'}
h={'100%'}
/>
) : (
<Image
src={'https://placehold.co/800x450?text=Upload%20an%20Image'}
w={'100%'}
h={'100%'}
/>
)}
</Card>
<FiPlus />
</Button>
</Group>
<Group w={'100%'} justify='center'>
<Button
w={'min-content'}
disabled={!background}
onClick={() => {
if (background) {
const newBackground = new File(
[background],
newFileName || background.name,
{ type: background.type },
);
fd.append('background', newBackground || '');
uploadAsync({
method: 'POST',
endpoint: 'api/backgrounds',
body: fd,
});
)}
{confirm && (
<DeleteBackground
fileName={fileName}
setFileName={setFileName}
inUseBackgrounds={inUseBackgrounds}
setBackground={setBackground}
setNewFileName={setNewFileName}
setConfirm={setConfirm}
/>
)}
{editing && (
<EditBackground
fileName={fileName}
setFileName={setFileName}
inUseBackgrounds={inUseBackgrounds}
setBackground={setBackground}
setNewFileName={setNewFileName}
setEditing={setEditing}
/>
)}
{!editing && !confirm && !adding && (
<ScrollArea
className={scrollAreaClasses.default}
classNames={scrollAreaClasses}
type={'always'}
style={{
width: '100%',
height: '30rem',
backgroundColor: 'var(--mantine-color-search-0)',
padding: '1rem',
borderRadius: '.5rem',
backgroundFilter: 'blur(5px)',
}}
>
<SimpleGrid w={'100%'} cols={3} p={'.75rem'}>
{backgroundList
.filter((background) => background !== 'None')
.filter(
(background) =>
!debouncedSearch ||
background
.toLocaleLowerCase()
.includes(debouncedSearch.toLocaleLowerCase()),
)
.map((background) => (
<Group
onMouseEnter={() => {
setHovered(background);
}}
onMouseLeave={() => {
setHovered('');
}}
key={background}
display={'flex'}
pos={'relative'}
style={{
borderRadius: '.5rem',
backgroundColor:
hovered === background
? 'var(--mantine-color-search-0)'
: undefined,
}}
>
<Text
style={{
color: 'var(--mantine-color-background-0)',
backgroundColor: 'var(--mantine-color-primary-0)',
padding: '.25rem',
borderRadius: '.5rem',
position: 'absolute',
top: '-.25rem',
left: 0,
zIndex: 3,
boxShadow: '2px 2px var(--mantine-color-accent-0)',
textOverflow: 'ellipsis',
overflow: 'hidden',
whiteSpace: 'nowrap',
maxWidth: width,
}}
>
{background}
</Text>
<Card
ref={ref}
style={{
aspectRatio: '16/9',
width: '100%',
backgroundImage: `url(../../api/backgroundImages/thumbs/${background})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
padding: '2rem',
margin: '1rem',
cursor: 'zoom-in',
}}
onClick={() => {
setLightboxName(background);
open();
}}
/>
<ActionIcon
style={{
position: 'absolute',
bottom: '.5rem',
right: '2.5rem',
zIndex: 3,
}}
onClick={() => {
setFileName(background);
setEditing(true);
}}
>
<FiEdit />
</ActionIcon>
<ActionIcon
color='var(--mantine-color-red-6)'
style={{
position: 'absolute',
bottom: '.5rem',
right: '.5rem',
zIndex: 3,
}}
onClick={() => {
setFileName(background);
setConfirm(true);
}}
>
<FiTrash color='black' />
</ActionIcon>
</Group>
))}
</SimpleGrid>
</ScrollArea>
)}
{adding && (
<Stack
display={'flex'}
pos={'relative'}
w={'100%'}
align={'center'}
justify='space-between'
p={16}
>
<Group gap={0}>
<Stack gap={0} w={'60%'}>
<FileInput
clearable
accept='image/png,image/jpeg'
value={background}
onChange={handleFileUpload}
label={'Upload Background'}
placeholder={'Select...'}
error={err && 'Please upload a background'}
description={
'Max size: 50MB for upload. Images are resized to 300kb after upload.'
}
pr={'xl'}
pl={0}
styles={{
input: {
color: 'var(--mantine-color-primary-0)',
borderColor: 'var(--mantine-color-primary-0)',
},
placeholder: {
color: 'var(--mantine-color-accent-0)',
},
}}
/>
<TextInput
label={'File Name'}
placeholder={fileName}
value={newFileName}
onChange={(e) => setNewFileName(e.target.value)}
pr={'xl'}
pl={0}
styles={{
input: {
color: 'var(--mantine-color-primary-0)',
borderColor: 'var(--mantine-color-primary-0)',
},
}}
/>
</Stack>
<Card
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,
}}
>
{background ? (
<Image
src={URL.createObjectURL(background)}
w={'100%'}
h={'100%'}
/>
) : (
<Image
src={'https://placehold.co/800x450?text=Upload%20an%20Image'}
w={'100%'}
h={'100%'}
/>
)}
</Card>
</Group>
<Group w={'100%'} justify='center'>
<Button
w={'min-content'}
disabled={!background}
onClick={() => {
if (background) {
const extension = background.name.substring(
background.name.lastIndexOf('.'),
);
const validatedName = newFileName.endsWith(extension)
? newFileName
: `${newFileName}${extension}`;
const newBackground = new File(
[background],
validatedName || background.name,
{ type: background.type },
);
fd.append('background', newBackground || '');
uploadAsync({
method: 'POST',
endpoint: 'api/backgrounds',
body: fd,
});
setAdding(false);
setBackground(null);
setNewFileName('');
setErr(false);
} else {
setErr(true);
}
}}
>
Upload
</Button>
<Button
w={'min-content'}
color='var(--mantine-color-red-6)'
onClick={() => {
setAdding(false);
setBackground(null);
setNewFileName('');
setErr(false);
} else {
setErr(true);
}
}}
>
Upload
</Button>
<Button
w={'min-content'}
color='var(--mantine-color-red-6)'
onClick={() => {
setAdding(false);
setBackground(null);
setNewFileName('');
setErr(false);
}}
>
Cancel
</Button>
</Group>
</Stack>
)}
</Stack>
</Modal.Body>
</Modal.Content>
</Modal.Root>
}}
>
Cancel
</Button>
</Group>
</Stack>
)}
</Stack>
</Modal.Body>
</Modal.Content>
</Modal.Root>
</>
);
}

View File

@@ -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',

View File

@@ -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.
</Text>
)}
<Group h={'100%'} mb={'1rem'}>
<Stack h={'100%'} mb={'1rem'}>
<TextInput
className={textInputClasses.settingsItem}
classNames={textInputClasses}
@@ -56,19 +55,8 @@ export function EditBackground({
: undefined
}
/>
<Card
style={{
aspectRatio: '16/9',
height: '100%',
backgroundImage: `url(../../api/backgroundImages/${fileName})`,
backgroundSize: 'cover',
backgroundPosition: 'center',
backgroundRepeat: 'no-repeat',
padding: '2rem',
margin: '1rem',
}}
/>
</Group>
<Image src={`../../api/backgroundImages/thumbs/${fileName}`} />
</Stack>
<Group>
<Button
mt={'auto'}

View File

@@ -114,7 +114,7 @@ export function ThemeCard({
style={{
backgroundImage:
cardTheme?.backgroundImage.toLocaleLowerCase() !== 'none'
? `linear-gradient(${cardTheme?.backgroundColor}33, ${cardTheme?.backgroundColor}33), url(../../api/backgroundImages/${cardTheme?.backgroundImage})`
? `linear-gradient(${cardTheme?.backgroundColor}33, ${cardTheme?.backgroundColor}33), url(../../api/backgroundImages/thumbs/${cardTheme?.backgroundImage})`
: undefined,
backgroundSize:
cardTheme?.backgroundImage.toLocaleLowerCase() !== 'none'

View File

@@ -14,7 +14,7 @@ export function ThemeMiniCard({ miniTheme }: { miniTheme: Theme | undefined }) {
style={{
backgroundImage:
miniTheme?.backgroundImage.toLocaleLowerCase() !== 'none'
? `linear-gradient(${miniTheme?.backgroundColor}33, ${miniTheme?.backgroundColor}33), url(../../api/backgroundImages/${miniTheme?.backgroundImage})`
? `linear-gradient(${miniTheme?.backgroundColor}33, ${miniTheme?.backgroundColor}33), url(../../api/backgroundImages/thumbs/${miniTheme?.backgroundImage})`
: undefined,
backgroundSize:
miniTheme?.backgroundImage.toLocaleLowerCase() !== 'none' ? 'cover' : undefined,

View File

@@ -5,6 +5,7 @@ import {
ColorPicker,
ColorSwatch,
Group,
Image,
Modal,
ScrollArea,
Stack,
@@ -42,7 +43,7 @@ export function ThemeModal({
closePicker: () => void;
handleSaveTheme: () => void;
}) {
const { isMobile, theme } = useCommonHooks();
const { isMobile, theme, getObjectDiff } = useCommonHooks();
const viewportRef = useRef<HTMLDivElement>(null);
const [query, setQuery] = useState('');
const [hovered, setHovered] = useState(-1);
@@ -71,8 +72,8 @@ export function ThemeModal({
background:
item !== 'none' && item !== 'None'
? index === hovered
? `linear-gradient(${selectedTheme.backgroundColor}88, ${selectedTheme.backgroundColor}88), no-repeat center url(../../api/backgroundImages/${item})`
: `no-repeat center url(../../api/backgroundImages/${item})`
? `linear-gradient(${selectedTheme.backgroundColor}88, ${selectedTheme.backgroundColor}88), no-repeat center url(../../api/backgroundImages/thumbs/${item})`
: `no-repeat center url(../../api/backgroundImages/thumbs/${item})`
: 'repeating-linear-gradient(45deg, #33333366, #33333366 10px, #88888866 10px, #88888866 20px)',
backgroundSize: item !== 'none' ? 'cover' : undefined,
backgroundColor: item === 'none' ? '#00000088' : undefined,
@@ -491,27 +492,131 @@ export function ThemeModal({
</Stack>
)}
{!pickerOpen && !backgroundPicker && (
<Stack h={'100%'} align='center' justify='center' gap={4}>
<Checkbox
label='Text Shadows'
checked={selectedTheme.textShadowsEnabled === 1}
onChange={(e) => {
setSelectedTheme({
...selectedTheme,
textShadowsEnabled: e.target.checked ? 1 : 0,
});
}}
/>
<Checkbox
label='App Shadows'
checked={selectedTheme.appShadowsEnabled === 1}
onChange={(e) => {
setSelectedTheme({
...selectedTheme,
appShadowsEnabled: e.target.checked ? 1 : 0,
});
}}
/>
<Stack h={'100%'} justify='space-between' align='center' gap={4}>
<Stack w={'100%'} align='center' gap={4}>
<Checkbox
label='Text Shadows'
checked={selectedTheme.textShadowsEnabled === 1}
onChange={(e) => {
setSelectedTheme({
...selectedTheme,
textShadowsEnabled: e.target.checked ? 1 : 0,
});
}}
styles={{
root: { width: '50%' },
body: {
width: '100%',
display: 'flex',
justifyContent: 'space-between',
},
}}
/>
<Checkbox
label='App Shadows'
checked={selectedTheme.appShadowsEnabled === 1}
onChange={(e) => {
setSelectedTheme({
...selectedTheme,
appShadowsEnabled: e.target.checked ? 1 : 0,
});
}}
styles={{
root: { width: '50%' },
body: {
width: '100%',
display: 'flex',
justifyContent: 'space-between',
},
}}
/>
</Stack>
{JSON.stringify(defaultTheme) !== JSON.stringify(selectedTheme) && (
<>
<Text fz={'1.5rem'}>Changes:</Text>
<ScrollArea.Autosize
w={'100%'}
className={scrollAreaClasses.default}
classNames={scrollAreaClasses}
style={{
backgroundColor: 'var(--mantine-color-accent-0)',
borderRadius: 8,
padding: '1rem',
}}
>
<Stack w={'100%'} gap={0}>
{getObjectDiff(defaultTheme, designerTheme) !== null &&
Object.keys(getObjectDiff(defaultTheme, designerTheme)).map(
(key: any) => {
return (
<Stack
w={'100%'}
align='center'
justify='center'
gap={0}
key={key}
>
<Text key={key}>{key}</Text>
{key === 'name' && (
<Group w={'100%'} justify='center'>
<Text>{defaultTheme[key as keyof Theme]}</Text>
<Text>→</Text>
<Text>{designerTheme[key as keyof Theme]}</Text>
</Group>
)}
{key === 'backgroundImage' && (
<Group w={'100%'} justify='center'>
<Image
w={'40%'}
src={`../../api/backgroundImages/thumbs/${defaultTheme[key as keyof Theme] as string}`}
alt='None'
/>
<Text>→</Text>
<Image
w={'40%'}
src={`../../api/backgroundImages/thumbs/${designerTheme[key as keyof Theme] as string}`}
alt='None'
/>
</Group>
)}
{key.includes('Color') && (
<Group w={'100%'} justify='center'>
<ColorSwatch
color={
defaultTheme[key as keyof Theme] as string
}
/>
<Text>→</Text>
<ColorSwatch
color={
designerTheme[key as keyof Theme] as string
}
/>
</Group>
)}
{key.includes('Shadow') && (
<Group w={'100%'} justify='center'>
{defaultTheme[key as keyof Theme] === 0 ? (
<Text>Off</Text>
) : (
<Text>On</Text>
)}
<Text>→</Text>
{designerTheme[key as keyof Theme] === 0 ? (
<Text>Off</Text>
) : (
<Text>On</Text>
)}
</Group>
)}
</Stack>
);
},
)}
</Stack>
</ScrollArea.Autosize>
</>
)}
<Button
onClick={() => {
setSelectedTheme({ ...defaultTheme });

View File

@@ -10,7 +10,7 @@ export function ThemeModalContent({ selectedTheme }: { selectedTheme: Theme }) {
style={{
backgroundImage:
selectedTheme?.backgroundImage.toLocaleLowerCase() !== 'none'
? `linear-gradient(${selectedTheme?.backgroundColor}33, ${selectedTheme?.backgroundColor}33), url(../../api/backgroundImages/${selectedTheme?.backgroundImage})`
? `linear-gradient(${selectedTheme?.backgroundColor}33, ${selectedTheme?.backgroundColor}33), url(../../api/backgroundImages/thumbs/${selectedTheme?.backgroundImage})`
: undefined,
backgroundSize:
selectedTheme?.backgroundImage.toLocaleLowerCase() !== 'none'

View File

@@ -61,7 +61,7 @@ export function ThemeSelect({
color: theme?.primaryColor,
backgroundImage:
theme?.backgroundImage.toLocaleLowerCase() !== 'none'
? `linear-gradient(${theme?.backgroundColor}33, ${theme?.backgroundColor}33), url(../../api/backgroundImages/${theme?.backgroundImage})`
? `linear-gradient(${theme?.backgroundColor}33, ${theme?.backgroundColor}33), url(../../api/backgroundImages/thumbs/${theme?.backgroundImage})`
: undefined,
backgroundSize:
theme?.backgroundImage.toLocaleLowerCase() !== 'none' ? 'cover' : undefined,
@@ -88,7 +88,7 @@ export function ThemeSelect({
style={{
backgroundImage:
theme?.backgroundImage.toLocaleLowerCase() !== 'none'
? `linear-gradient(${theme?.backgroundColor}33, ${theme?.backgroundColor}33), url(../../api/backgroundImages/${theme?.backgroundImage})`
? `linear-gradient(${theme?.backgroundColor}33, ${theme?.backgroundColor}33), url(../../api/backgroundImages/thumbs/${theme?.backgroundImage})`
: undefined,
backgroundSize:
theme?.backgroundImage.toLocaleLowerCase() !== 'none'