New Theme modal
This commit is contained in:
16
package-lock.json
generated
16
package-lock.json
generated
@@ -32,7 +32,7 @@
|
|||||||
"@vitest/coverage-v8": "^3.2.4",
|
"@vitest/coverage-v8": "^3.2.4",
|
||||||
"@vitest/ui": "^3.2.4",
|
"@vitest/ui": "^3.2.4",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.8.3",
|
||||||
"vite": "^7.0.5",
|
"vite": "^7.0.6",
|
||||||
"vite-plugin-dts": "~4.5.4",
|
"vite-plugin-dts": "~4.5.4",
|
||||||
"vite-tsconfig-paths": "^5.1.4",
|
"vite-tsconfig-paths": "^5.1.4",
|
||||||
"vitest": "^3.2.4"
|
"vitest": "^3.2.4"
|
||||||
@@ -3468,9 +3468,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/picomatch": {
|
"node_modules/picomatch": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz",
|
||||||
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -4506,15 +4506,15 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "7.0.5",
|
"version": "7.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-7.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-7.0.6.tgz",
|
||||||
"integrity": "sha512-1mncVwJxy2C9ThLwz0+2GKZyEXuC3MyWtAAlNftlZZXZDP3AJt5FmwcMit/IGGaNZ8ZOB2BNO/HFUB+CpN0NQw==",
|
"integrity": "sha512-MHFiOENNBd+Bd9uvc8GEsIzdkn1JxMmEeYX35tI3fv0sJBUTfW5tQsoaOwuY4KhBI09A3dUJ/DXf2yxPVPUceg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.25.0",
|
"esbuild": "^0.25.0",
|
||||||
"fdir": "^6.4.6",
|
"fdir": "^6.4.6",
|
||||||
"picomatch": "^4.0.2",
|
"picomatch": "^4.0.3",
|
||||||
"postcss": "^8.5.6",
|
"postcss": "^8.5.6",
|
||||||
"rollup": "^4.40.0",
|
"rollup": "^4.40.0",
|
||||||
"tinyglobby": "^0.2.14"
|
"tinyglobby": "^0.2.14"
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
"@vitest/coverage-v8": "^3.2.4",
|
"@vitest/coverage-v8": "^3.2.4",
|
||||||
"@vitest/ui": "^3.2.4",
|
"@vitest/ui": "^3.2.4",
|
||||||
"typescript": "^5.8.3",
|
"typescript": "^5.8.3",
|
||||||
"vite": "^7.0.5",
|
"vite": "^7.0.6",
|
||||||
"vite-plugin-dts": "~4.5.4",
|
"vite-plugin-dts": "~4.5.4",
|
||||||
"vite-tsconfig-paths": "^5.1.4",
|
"vite-tsconfig-paths": "^5.1.4",
|
||||||
"vitest": "^3.2.4"
|
"vitest": "^3.2.4"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Button, Group, Modal, SimpleGrid, Text, TextInput } from '@mantine/core';
|
import { Button, Group, Modal, Text, TextInput } from '@mantine/core';
|
||||||
import { useCommonHooks } from 'hooks';
|
import { useCommonHooks } from 'hooks';
|
||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { modalClasses, textInputClasses } from 'styles';
|
import { modalClasses, textInputClasses } from 'styles';
|
||||||
@@ -87,7 +87,7 @@ export function ThemePlaylistModal({
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<SimpleGrid cols={3}>
|
<Group w={'100%'} justify='center'>
|
||||||
{selectedPlaylist?.name !== 'Time of Day' &&
|
{selectedPlaylist?.name !== 'Time of Day' &&
|
||||||
allThemes?.map((miniTheme: Theme) => {
|
allThemes?.map((miniTheme: Theme) => {
|
||||||
const newThemeList = themeList;
|
const newThemeList = themeList;
|
||||||
@@ -102,7 +102,7 @@ export function ThemePlaylistModal({
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</SimpleGrid>
|
</Group>
|
||||||
<Group mt={'1rem'}>
|
<Group mt={'1rem'}>
|
||||||
<Button color={'green'} onClick={handleSavePlaylist}>
|
<Button color={'green'} onClick={handleSavePlaylist}>
|
||||||
Save
|
Save
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
import {
|
import {
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
|
Box,
|
||||||
Button,
|
Button,
|
||||||
Checkbox,
|
Checkbox,
|
||||||
ColorPicker,
|
ColorPicker,
|
||||||
ColorSwatch,
|
ColorSwatch,
|
||||||
|
Divider,
|
||||||
Group,
|
Group,
|
||||||
Image,
|
Image,
|
||||||
Modal,
|
Modal,
|
||||||
|
Overlay,
|
||||||
ScrollArea,
|
ScrollArea,
|
||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
@@ -14,13 +17,17 @@ import {
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
UnstyledButton,
|
UnstyledButton,
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useDisclosure } from '@mantine/hooks';
|
import { useDisclosure, useLongPress } from '@mantine/hooks';
|
||||||
import { useCommonHooks } from 'hooks';
|
import { useCommonHooks } from 'hooks';
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
|
import { FaArrowRight } from 'react-icons/fa';
|
||||||
import { FiImage, FiSave, FiX } from 'react-icons/fi';
|
import { FiImage, FiSave, FiX } from 'react-icons/fi';
|
||||||
import { modalClasses, scrollAreaClasses, textClasses, textInputClasses } from 'styles';
|
import { modalClasses, scrollAreaClasses, textClasses, textInputClasses } from 'styles';
|
||||||
import { BackgroundProperties, type Theme } from 'types';
|
import { BackgroundProperties, type Theme } from 'types';
|
||||||
|
import { ThemeCard } from './ThemeCard';
|
||||||
|
import { ThemeMiniCard } from './ThemeMiniCard';
|
||||||
import { ThemeModalContent } from './ThemeModalContent';
|
import { ThemeModalContent } from './ThemeModalContent';
|
||||||
|
import { ThemePreviewMiddleware } from './ThemePreviewMiddleware';
|
||||||
|
|
||||||
export function ThemeModal({
|
export function ThemeModal({
|
||||||
opened,
|
opened,
|
||||||
@@ -32,6 +39,9 @@ export function ThemeModal({
|
|||||||
pickerOpen,
|
pickerOpen,
|
||||||
closePicker,
|
closePicker,
|
||||||
handleSaveTheme,
|
handleSaveTheme,
|
||||||
|
isNew,
|
||||||
|
setIsNew,
|
||||||
|
allThemes,
|
||||||
}: {
|
}: {
|
||||||
opened: boolean;
|
opened: boolean;
|
||||||
handleClose: () => void;
|
handleClose: () => void;
|
||||||
@@ -42,7 +52,14 @@ export function ThemeModal({
|
|||||||
pickerOpen: boolean;
|
pickerOpen: boolean;
|
||||||
closePicker: () => void;
|
closePicker: () => void;
|
||||||
handleSaveTheme: () => void;
|
handleSaveTheme: () => void;
|
||||||
|
isNew: boolean;
|
||||||
|
setIsNew: (isNew: boolean) => void;
|
||||||
|
allThemes: Theme[];
|
||||||
}) {
|
}) {
|
||||||
|
const [pressed, setPressed] = useState<any>(false);
|
||||||
|
const handlers = useLongPress(() => {
|
||||||
|
setPressed(true);
|
||||||
|
});
|
||||||
const { isMobile, theme, getObjectDiff } = useCommonHooks();
|
const { isMobile, theme, getObjectDiff } = useCommonHooks();
|
||||||
const viewportRef = useRef<HTMLDivElement>(null);
|
const viewportRef = useRef<HTMLDivElement>(null);
|
||||||
const [query, setQuery] = useState('');
|
const [query, setQuery] = useState('');
|
||||||
@@ -56,6 +73,7 @@ export function ThemeModal({
|
|||||||
const filtered = backgroundList.filter((item: string) =>
|
const filtered = backgroundList.filter((item: string) =>
|
||||||
item.toLowerCase().includes(query.toLowerCase()),
|
item.toLowerCase().includes(query.toLowerCase()),
|
||||||
);
|
);
|
||||||
|
const [duplicate, setDuplicate] = useState(false);
|
||||||
|
|
||||||
const [backgroundPicker, { open: openBackgroundPicker, close: closeBackgroundPicker }] =
|
const [backgroundPicker, { open: openBackgroundPicker, close: closeBackgroundPicker }] =
|
||||||
useDisclosure(false);
|
useDisclosure(false);
|
||||||
@@ -140,13 +158,17 @@ export function ThemeModal({
|
|||||||
className={modalClasses.editThemeModal}
|
className={modalClasses.editThemeModal}
|
||||||
classNames={modalClasses}
|
classNames={modalClasses}
|
||||||
opened={opened}
|
opened={opened}
|
||||||
onClose={handleClose}
|
onClose={() => {
|
||||||
|
handleClose();
|
||||||
|
setDuplicate(false);
|
||||||
|
}}
|
||||||
fullScreen={isMobile}
|
fullScreen={isMobile}
|
||||||
centered
|
centered
|
||||||
>
|
>
|
||||||
<Modal.Overlay />
|
<Modal.Overlay />
|
||||||
<Modal.Content>
|
<Modal.Content>
|
||||||
<Modal.Header style={{ justifyContent: 'center' }}>
|
<Modal.Header style={{ justifyContent: 'center' }}>
|
||||||
|
{!isNew && (
|
||||||
<Group pos={'absolute'}>
|
<Group pos={'absolute'}>
|
||||||
<Text c={'var(--mantine-color-background-0)'}>Name:</Text>
|
<Text c={'var(--mantine-color-background-0)'}>Name:</Text>
|
||||||
<TextInput
|
<TextInput
|
||||||
@@ -169,9 +191,228 @@ export function ThemeModal({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
|
)}
|
||||||
<Modal.CloseButton />
|
<Modal.CloseButton />
|
||||||
</Modal.Header>
|
</Modal.Header>
|
||||||
<Modal.Body>
|
<Modal.Body>
|
||||||
|
{isNew ? (
|
||||||
|
<Stack align='center' p={'2rem'}>
|
||||||
|
{!duplicate ? (
|
||||||
|
<>
|
||||||
|
<Text className={textClasses.settingsSubTitle} classNames={textClasses}>
|
||||||
|
Please choose an option:
|
||||||
|
</Text>
|
||||||
|
<Group>
|
||||||
|
<Stack
|
||||||
|
justify='center'
|
||||||
|
align='center'
|
||||||
|
bg={'var(--mantine-color-accent-0)'}
|
||||||
|
px={'1rem'}
|
||||||
|
py={'3rem'}
|
||||||
|
style={{ borderRadius: '8px' }}
|
||||||
|
>
|
||||||
|
<ThemeCard
|
||||||
|
cardTheme={{
|
||||||
|
id: undefined,
|
||||||
|
name: 'Default',
|
||||||
|
backgroundImage: 'none',
|
||||||
|
backgroundColor: '#EEEEEE',
|
||||||
|
searchColor: '#00000033',
|
||||||
|
primaryColor: '#222222',
|
||||||
|
accentColor: '#5c5c5c',
|
||||||
|
borderColor: '#5c5c5c',
|
||||||
|
randomEnabled: 1,
|
||||||
|
textShadowsEnabled: 0,
|
||||||
|
appShadowsEnabled: 0,
|
||||||
|
}}
|
||||||
|
handleOpen={() => {}}
|
||||||
|
allThemes={[]}
|
||||||
|
themePlaylists={[]}
|
||||||
|
/>
|
||||||
|
<Button
|
||||||
|
pos={'absolute'}
|
||||||
|
w={'275px'}
|
||||||
|
h={'115px'}
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
boxShadow: '3px 3px var(--mantine-color-border-0)',
|
||||||
|
}}
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
backgroundColor: 'var(--mantine-color-primary-0)',
|
||||||
|
height: 'min-content',
|
||||||
|
padding: '.5rem',
|
||||||
|
borderRadius: 4,
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: '0',
|
||||||
|
fontSize: '1rem',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
onClick={() => setIsNew(false)}
|
||||||
|
>
|
||||||
|
New Theme from Scratch
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
<Divider
|
||||||
|
color={'var(--mantine-color-primary-0)'}
|
||||||
|
my={'sm'}
|
||||||
|
orientation='vertical'
|
||||||
|
m={'2rem'}
|
||||||
|
/>
|
||||||
|
<Stack
|
||||||
|
justify='center'
|
||||||
|
align='center'
|
||||||
|
pos={'relative'}
|
||||||
|
bg={'var(--mantine-color-accent-0)'}
|
||||||
|
px={'1rem'}
|
||||||
|
py={'3rem'}
|
||||||
|
style={{ borderRadius: '8px' }}
|
||||||
|
>
|
||||||
|
<ThemeCard
|
||||||
|
cardTheme={{
|
||||||
|
id: undefined,
|
||||||
|
name: 'Theme',
|
||||||
|
backgroundImage: 'none',
|
||||||
|
backgroundColor: '#263238',
|
||||||
|
searchColor: '#AABBC320',
|
||||||
|
primaryColor: '#AABBC3',
|
||||||
|
accentColor: '#aeea00',
|
||||||
|
borderColor: '#aeea00',
|
||||||
|
randomEnabled: 1,
|
||||||
|
textShadowsEnabled: 0,
|
||||||
|
appShadowsEnabled: 0,
|
||||||
|
}}
|
||||||
|
handleOpen={() => {}}
|
||||||
|
allThemes={[]}
|
||||||
|
themePlaylists={[]}
|
||||||
|
/>
|
||||||
|
<Overlay
|
||||||
|
bg={'transparent'}
|
||||||
|
zIndex={0}
|
||||||
|
pos={'absolute'}
|
||||||
|
w={'275px'}
|
||||||
|
h={'115px'}
|
||||||
|
top={'3rem'}
|
||||||
|
left={'1rem'}
|
||||||
|
style={{
|
||||||
|
backdropFilter: 'grayscale(80%) brightness(80%)',
|
||||||
|
mask: 'linear-gradient(105deg, rgba(0, 0, 0, 1) 48%, rgba(0, 0, 0, 0) 52%)',
|
||||||
|
alignContent: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
display: 'flex',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<FaArrowRight size={35} style={{ position: 'absolute' }} />
|
||||||
|
<Button
|
||||||
|
pos={'absolute'}
|
||||||
|
w={'275px'}
|
||||||
|
h={'115px'}
|
||||||
|
style={{
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
boxShadow: '3px 3px var(--mantine-color-border-0)',
|
||||||
|
}}
|
||||||
|
styles={{
|
||||||
|
label: {
|
||||||
|
backgroundColor: 'var(--mantine-color-primary-0)',
|
||||||
|
height: 'min-content',
|
||||||
|
padding: '.5rem',
|
||||||
|
borderRadius: 4,
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: '0',
|
||||||
|
fontSize: '1rem',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
onClick={() => setDuplicate(true)}
|
||||||
|
>
|
||||||
|
Duplicate existing Theme
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Group>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<Stack align='center'>
|
||||||
|
<Group
|
||||||
|
w={'100%'}
|
||||||
|
justify='center'
|
||||||
|
style={{
|
||||||
|
backgroundColor:
|
||||||
|
'color-mix(in srgb, var(--mantine-color-accent-0), var(--mantine-color-background-0))',
|
||||||
|
padding: '1rem',
|
||||||
|
borderRadius: '8px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{allThemes?.map((miniTheme: Theme) => {
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
{...handlers}
|
||||||
|
key={miniTheme.id}
|
||||||
|
onClick={() => {
|
||||||
|
!pressed && setSelectedTheme(miniTheme);
|
||||||
|
setPressed(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ThemePreviewMiddleware
|
||||||
|
newThemeList={[miniTheme.id as number]}
|
||||||
|
miniTheme={miniTheme}
|
||||||
|
themeList={[]}
|
||||||
|
selectedPlaylist={undefined}
|
||||||
|
setSelectedPlaylist={() => {}}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</Group>
|
||||||
|
<Group>
|
||||||
|
<Group
|
||||||
|
style={{
|
||||||
|
backgroundColor:
|
||||||
|
'color-mix(in srgb, var(--mantine-color-primary-0), var(--mantine-color-background-0))',
|
||||||
|
padding: '1rem',
|
||||||
|
borderRadius: '8px',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<ThemeMiniCard miniTheme={selectedTheme} />
|
||||||
|
<Button
|
||||||
|
disabled={selectedTheme.name === 'default'}
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedTheme({
|
||||||
|
...selectedTheme,
|
||||||
|
name: `${selectedTheme.name} copy`,
|
||||||
|
});
|
||||||
|
setIsNew(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Confirm
|
||||||
|
</Button>
|
||||||
|
</Group>
|
||||||
|
<Button
|
||||||
|
color={'red'}
|
||||||
|
styles={{ label: { color: 'black' } }}
|
||||||
|
onClick={() => {
|
||||||
|
setDuplicate(false);
|
||||||
|
setSelectedTheme({
|
||||||
|
id: undefined,
|
||||||
|
name: 'Default',
|
||||||
|
backgroundImage: 'none',
|
||||||
|
backgroundColor: '#EEEEEE',
|
||||||
|
searchColor: '#00000033',
|
||||||
|
primaryColor: '#222222',
|
||||||
|
accentColor: '#5c5c5c',
|
||||||
|
borderColor: '#5c5c5c',
|
||||||
|
randomEnabled: 1,
|
||||||
|
textShadowsEnabled: 0,
|
||||||
|
appShadowsEnabled: 0,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Back
|
||||||
|
</Button>
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
<Group p={'2rem'} w={'100%'} align='flex-start' justify='space-between'>
|
<Group p={'2rem'} w={'100%'} align='flex-start' justify='space-between'>
|
||||||
<Stack display={'flex'} pos={'relative'} w={isMobile ? '100%' : '70%'}>
|
<Stack display={'flex'} pos={'relative'} w={isMobile ? '100%' : '70%'}>
|
||||||
<ThemeModalContent selectedTheme={designerTheme} />
|
<ThemeModalContent selectedTheme={designerTheme} />
|
||||||
@@ -305,7 +546,11 @@ export function ThemeModal({
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Change{' '}
|
Change{' '}
|
||||||
{BackgroundProperties[colorId as keyof typeof BackgroundProperties]}
|
{
|
||||||
|
BackgroundProperties[
|
||||||
|
colorId as keyof typeof BackgroundProperties
|
||||||
|
]
|
||||||
|
}
|
||||||
</Text>
|
</Text>
|
||||||
{colorId === 'backgroundColor' && (
|
{colorId === 'backgroundColor' && (
|
||||||
<ColorPicker
|
<ColorPicker
|
||||||
@@ -547,8 +792,9 @@ export function ThemeModal({
|
|||||||
>
|
>
|
||||||
<Stack w={'100%'} gap={0}>
|
<Stack w={'100%'} gap={0}>
|
||||||
{getObjectDiff(defaultTheme, designerTheme) !== null &&
|
{getObjectDiff(defaultTheme, designerTheme) !== null &&
|
||||||
Object.keys(getObjectDiff(defaultTheme, designerTheme)).map(
|
Object.keys(
|
||||||
(key: any) => {
|
getObjectDiff(defaultTheme, designerTheme),
|
||||||
|
).map((key: any) => {
|
||||||
return (
|
return (
|
||||||
<Stack
|
<Stack
|
||||||
w={'100%'}
|
w={'100%'}
|
||||||
@@ -588,7 +834,9 @@ export function ThemeModal({
|
|||||||
w={'40%'}
|
w={'40%'}
|
||||||
src={
|
src={
|
||||||
(
|
(
|
||||||
designerTheme[key as keyof Theme] as string
|
designerTheme[
|
||||||
|
key as keyof Theme
|
||||||
|
] as string
|
||||||
).toLocaleLowerCase() === 'none'
|
).toLocaleLowerCase() === 'none'
|
||||||
? 'https://placehold.co/540x360?text=None'
|
? 'https://placehold.co/540x360?text=None'
|
||||||
: `../../api/backgroundImages/thumbs/${designerTheme[key as keyof Theme] as string}`
|
: `../../api/backgroundImages/thumbs/${designerTheme[key as keyof Theme] as string}`
|
||||||
@@ -628,8 +876,7 @@ export function ThemeModal({
|
|||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
},
|
})}
|
||||||
)}
|
|
||||||
</Stack>
|
</Stack>
|
||||||
</ScrollArea.Autosize>
|
</ScrollArea.Autosize>
|
||||||
</>
|
</>
|
||||||
@@ -648,7 +895,9 @@ export function ThemeModal({
|
|||||||
</Group>
|
</Group>
|
||||||
<Group>
|
<Group>
|
||||||
<Button
|
<Button
|
||||||
disabled={JSON.stringify(defaultTheme) === JSON.stringify(selectedTheme)}
|
disabled={
|
||||||
|
JSON.stringify(defaultTheme) === JSON.stringify(selectedTheme)
|
||||||
|
}
|
||||||
color={'green'}
|
color={'green'}
|
||||||
onClick={handleSaveTheme}
|
onClick={handleSaveTheme}
|
||||||
>
|
>
|
||||||
@@ -660,11 +909,14 @@ export function ThemeModal({
|
|||||||
onClick={() => {
|
onClick={() => {
|
||||||
closeBackgroundPicker();
|
closeBackgroundPicker();
|
||||||
handleClose();
|
handleClose();
|
||||||
|
setDuplicate(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
</Button>
|
</Button>
|
||||||
</Group>
|
</Group>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Modal.Body>
|
</Modal.Body>
|
||||||
</Modal.Content>
|
</Modal.Content>
|
||||||
</Modal.Root>
|
</Modal.Root>
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export function Themes() {
|
|||||||
primaryColor: '#222222',
|
primaryColor: '#222222',
|
||||||
accentColor: '#5c5c5c',
|
accentColor: '#5c5c5c',
|
||||||
borderColor: '#5c5c5c',
|
borderColor: '#5c5c5c',
|
||||||
randomEnabled: 0,
|
randomEnabled: 1,
|
||||||
textShadowsEnabled: 0,
|
textShadowsEnabled: 0,
|
||||||
appShadowsEnabled: 0,
|
appShadowsEnabled: 0,
|
||||||
});
|
});
|
||||||
@@ -52,6 +52,7 @@ export function Themes() {
|
|||||||
const [searchValue, setSearchValue] = useState('');
|
const [searchValue, setSearchValue] = useState('');
|
||||||
const [debouncedSearch] = useDebouncedValue(searchValue, 500);
|
const [debouncedSearch] = useDebouncedValue(searchValue, 500);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
|
const [isNew, setIsNew] = useState(false);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const {
|
const {
|
||||||
currentTheme,
|
currentTheme,
|
||||||
@@ -70,6 +71,7 @@ export function Themes() {
|
|||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
closeThemeModal();
|
closeThemeModal();
|
||||||
closePicker();
|
closePicker();
|
||||||
|
setIsNew(false);
|
||||||
setSelectedTheme({
|
setSelectedTheme({
|
||||||
id: undefined,
|
id: undefined,
|
||||||
name: 'default',
|
name: 'default',
|
||||||
@@ -79,12 +81,17 @@ export function Themes() {
|
|||||||
primaryColor: '#222222',
|
primaryColor: '#222222',
|
||||||
accentColor: '#5c5c5c',
|
accentColor: '#5c5c5c',
|
||||||
borderColor: '#5c5c5c',
|
borderColor: '#5c5c5c',
|
||||||
randomEnabled: 0,
|
randomEnabled: 1,
|
||||||
textShadowsEnabled: 0,
|
textShadowsEnabled: 0,
|
||||||
appShadowsEnabled: 0,
|
appShadowsEnabled: 0,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleNewTheme = () => {
|
||||||
|
setIsNew(true);
|
||||||
|
openThemeModal();
|
||||||
|
};
|
||||||
|
|
||||||
const handleSaveTheme = () => {
|
const handleSaveTheme = () => {
|
||||||
mutateAsync({
|
mutateAsync({
|
||||||
method: selectedTheme?.id === undefined ? 'POST' : 'PATCH',
|
method: selectedTheme?.id === undefined ? 'POST' : 'PATCH',
|
||||||
@@ -147,6 +154,9 @@ export function Themes() {
|
|||||||
pickerOpen={pickerOpen}
|
pickerOpen={pickerOpen}
|
||||||
closePicker={closePicker}
|
closePicker={closePicker}
|
||||||
handleSaveTheme={handleSaveTheme}
|
handleSaveTheme={handleSaveTheme}
|
||||||
|
isNew={isNew}
|
||||||
|
setIsNew={setIsNew}
|
||||||
|
allThemes={allThemes}
|
||||||
/>
|
/>
|
||||||
<BackgroundModal
|
<BackgroundModal
|
||||||
backgroundModalOpened={backgroundModalOpened}
|
backgroundModalOpened={backgroundModalOpened}
|
||||||
@@ -156,7 +166,7 @@ export function Themes() {
|
|||||||
/>
|
/>
|
||||||
<SettingsHeader
|
<SettingsHeader
|
||||||
setDragging={undefined}
|
setDragging={undefined}
|
||||||
openModal={openThemeModal}
|
openModal={handleNewTheme}
|
||||||
title={'Themes'}
|
title={'Themes'}
|
||||||
tooltip={{
|
tooltip={{
|
||||||
title: 'Themes can be created here and applied to the homepage.',
|
title: 'Themes can be created here and applied to the homepage.',
|
||||||
|
|||||||
Reference in New Issue
Block a user