Fixes for theme editor logic
This commit is contained in:
@@ -68,14 +68,15 @@ export function ThemeModal({
|
||||
randomEnabled: 1,
|
||||
textShadowsEnabled: 0,
|
||||
appShadowsEnabled: 0,
|
||||
themeFont: null,
|
||||
});
|
||||
};
|
||||
|
||||
const handleSaveTheme = () => {
|
||||
mutateAsync({
|
||||
method: selectedTheme?.id === undefined ? 'POST' : 'PATCH',
|
||||
method: designerTheme?.id === undefined ? 'POST' : 'PATCH',
|
||||
endpoint: themesEndpoint,
|
||||
body: selectedTheme,
|
||||
body: designerTheme,
|
||||
});
|
||||
handleClose();
|
||||
};
|
||||
@@ -86,6 +87,7 @@ export function ThemeModal({
|
||||
setDefaultTheme(selectedTheme);
|
||||
}
|
||||
}, [selectedTheme]);
|
||||
|
||||
return (
|
||||
<Modal.Root
|
||||
size={'75%'}
|
||||
@@ -109,17 +111,17 @@ export function ThemeModal({
|
||||
<TextInput
|
||||
className={textInputClasses.default}
|
||||
classNames={textInputClasses}
|
||||
value={selectedTheme.name}
|
||||
value={designerTheme.name}
|
||||
onChange={(e) =>
|
||||
setSelectedTheme({ ...selectedTheme, name: e.target.value })
|
||||
setDesignerTheme({ ...designerTheme, name: e.target.value })
|
||||
}
|
||||
styles={{
|
||||
label: {
|
||||
color: 'var(--mantine-color-primary-0)',
|
||||
},
|
||||
input: {
|
||||
color: selectedTheme.primaryColor,
|
||||
backgroundColor: selectedTheme.backgroundColor,
|
||||
color: designerTheme.primaryColor,
|
||||
backgroundColor: designerTheme.backgroundColor,
|
||||
border: 'none',
|
||||
borderBottom: '1px solid var(--mantine-color-primary-0)',
|
||||
},
|
||||
@@ -217,22 +219,23 @@ export function ThemeModal({
|
||||
setIsNew={setIsNew}
|
||||
duplicate={duplicate}
|
||||
setDuplicate={setDuplicate}
|
||||
selectedTheme={selectedTheme}
|
||||
designerTheme={designerTheme}
|
||||
setDesignerTheme={setDesignerTheme}
|
||||
setSelectedTheme={setSelectedTheme}
|
||||
setDefaultTheme={setDefaultTheme}
|
||||
/>
|
||||
) : (
|
||||
<ThemeEditor
|
||||
designerTheme={designerTheme}
|
||||
setDesignerTheme={setDesignerTheme}
|
||||
selectedTheme={selectedTheme}
|
||||
closePicker={closePicker}
|
||||
handleSaveTheme={handleSaveTheme}
|
||||
backgroundList={backgroundList}
|
||||
defaultTheme={defaultTheme}
|
||||
selectedTheme={selectedTheme}
|
||||
designerTheme={designerTheme}
|
||||
setDesignerTheme={setDesignerTheme}
|
||||
openPicker={openPicker}
|
||||
pickerOpen={pickerOpen}
|
||||
setSelectedTheme={setSelectedTheme}
|
||||
closePicker={closePicker}
|
||||
handleClose={handleClose}
|
||||
handleSaveTheme={handleSaveTheme}
|
||||
duplicate={duplicate}
|
||||
setDuplicate={setDuplicate}
|
||||
/>
|
||||
|
||||
@@ -13,15 +13,19 @@ export function NewThemeStarter({
|
||||
setIsNew,
|
||||
duplicate,
|
||||
setDuplicate,
|
||||
selectedTheme,
|
||||
designerTheme,
|
||||
setDesignerTheme,
|
||||
setSelectedTheme,
|
||||
setDefaultTheme,
|
||||
}: {
|
||||
allThemes: Theme[];
|
||||
setIsNew: (isNew: boolean) => void;
|
||||
duplicate: boolean;
|
||||
setDuplicate: (duplicate: boolean) => void;
|
||||
selectedTheme: Theme;
|
||||
designerTheme: Theme;
|
||||
setDesignerTheme: (selectedTheme: Theme) => void;
|
||||
setSelectedTheme: (selectedTheme: Theme) => void;
|
||||
setDefaultTheme: (selectedTheme: Theme) => void;
|
||||
}) {
|
||||
const [pressed, setPressed] = useState<any>(false);
|
||||
const handlers = useLongPress(() => {
|
||||
@@ -55,7 +59,8 @@ export function NewThemeStarter({
|
||||
{...handlers}
|
||||
key={miniTheme.id}
|
||||
onClick={() => {
|
||||
!pressed && setSelectedTheme(miniTheme);
|
||||
!pressed && setDesignerTheme(miniTheme);
|
||||
!pressed && setDefaultTheme(miniTheme);
|
||||
setPressed(false);
|
||||
}}
|
||||
>
|
||||
@@ -79,13 +84,14 @@ export function NewThemeStarter({
|
||||
borderRadius: '8px',
|
||||
}}
|
||||
>
|
||||
<ThemeMiniCard miniTheme={selectedTheme} />
|
||||
<ThemeMiniCard miniTheme={designerTheme} />
|
||||
<Button
|
||||
disabled={selectedTheme.name === 'default'}
|
||||
disabled={designerTheme.name === 'default'}
|
||||
onClick={() => {
|
||||
setSelectedTheme({
|
||||
...selectedTheme,
|
||||
name: `${selectedTheme.name} copy`,
|
||||
setDesignerTheme({
|
||||
...designerTheme,
|
||||
id: undefined,
|
||||
name: `${designerTheme.name} copy`,
|
||||
});
|
||||
setIsNew(false);
|
||||
}}
|
||||
@@ -98,7 +104,7 @@ export function NewThemeStarter({
|
||||
styles={{ label: { color: 'black' } }}
|
||||
onClick={() => {
|
||||
setDuplicate(false);
|
||||
setSelectedTheme({
|
||||
setDesignerTheme({
|
||||
id: undefined,
|
||||
name: 'Default',
|
||||
backgroundImage: 'none',
|
||||
@@ -110,6 +116,7 @@ export function NewThemeStarter({
|
||||
randomEnabled: 1,
|
||||
textShadowsEnabled: 0,
|
||||
appShadowsEnabled: 0,
|
||||
themeFont: null,
|
||||
});
|
||||
}}
|
||||
>
|
||||
@@ -149,10 +156,11 @@ export function NewThemeStarter({
|
||||
randomEnabled: 1,
|
||||
textShadowsEnabled: 0,
|
||||
appShadowsEnabled: 0,
|
||||
themeFont: null,
|
||||
}}
|
||||
allThemes={[]}
|
||||
themePlaylists={[]}
|
||||
setSelectedTheme={setSelectedTheme}
|
||||
setSelectedTheme={setDesignerTheme}
|
||||
openThemeModal={() => {}}
|
||||
enabled={false}
|
||||
/>
|
||||
@@ -209,7 +217,7 @@ export function NewThemeStarter({
|
||||
cardTheme={randomTheme}
|
||||
allThemes={[]}
|
||||
themePlaylists={[]}
|
||||
setSelectedTheme={setSelectedTheme}
|
||||
setSelectedTheme={setDesignerTheme}
|
||||
openThemeModal={() => {}}
|
||||
enabled={false}
|
||||
/>
|
||||
@@ -261,6 +269,7 @@ export function NewThemeStarter({
|
||||
}}
|
||||
onClick={() => {
|
||||
setDuplicate(true);
|
||||
setDesignerTheme(randomTheme);
|
||||
setSelectedTheme(randomTheme);
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -37,10 +37,9 @@ import { ThemeModalContent } from './ThemeModalContent';
|
||||
export function ThemeEditor({
|
||||
backgroundList,
|
||||
defaultTheme,
|
||||
selectedTheme,
|
||||
designerTheme,
|
||||
setDesignerTheme,
|
||||
selectedTheme,
|
||||
setSelectedTheme,
|
||||
pickerOpen,
|
||||
openPicker,
|
||||
closePicker,
|
||||
@@ -51,10 +50,9 @@ export function ThemeEditor({
|
||||
}: {
|
||||
backgroundList: string[];
|
||||
defaultTheme: Theme;
|
||||
selectedTheme: Theme;
|
||||
designerTheme: Theme;
|
||||
setDesignerTheme: (theme: Theme) => void;
|
||||
selectedTheme: Theme;
|
||||
setSelectedTheme: (theme: Theme) => void;
|
||||
pickerOpen: boolean;
|
||||
openPicker: () => void;
|
||||
closePicker: () => void;
|
||||
@@ -78,27 +76,6 @@ export function ThemeEditor({
|
||||
const filtered = backgroundList.filter((item: string) =>
|
||||
item.toLowerCase().includes(query.toLowerCase()),
|
||||
);
|
||||
useEffect(() => {
|
||||
if (font) {
|
||||
setCustomFontEnabled(true);
|
||||
setSelectedTheme({
|
||||
...selectedTheme,
|
||||
themeFont: font,
|
||||
});
|
||||
} else {
|
||||
setCustomFontEnabled(false);
|
||||
setSelectedTheme({
|
||||
...selectedTheme,
|
||||
themeFont: null,
|
||||
});
|
||||
}
|
||||
}, [font]);
|
||||
useEffect(() => {
|
||||
if (selectedTheme) {
|
||||
setCustomFontEnabled(selectedTheme.themeFont !== null);
|
||||
setFont(selectedTheme.themeFont);
|
||||
}
|
||||
}, [selectedTheme]);
|
||||
const items = filtered.map((item: string, index: number) => {
|
||||
return (
|
||||
<UnstyledButton
|
||||
@@ -110,7 +87,7 @@ export function ThemeEditor({
|
||||
background:
|
||||
item !== 'none' && item !== 'None'
|
||||
? index === hovered
|
||||
? `linear-gradient(${selectedTheme.backgroundColor}88, ${selectedTheme.backgroundColor}88), no-repeat center url(../../api/backgroundImages/thumbs/${item})`
|
||||
? `linear-gradient(${designerTheme.backgroundColor}88, ${designerTheme.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' ? undefined : 'cover',
|
||||
@@ -173,7 +150,7 @@ export function ThemeEditor({
|
||||
setColorValue(colorValue || '');
|
||||
closeBackgroundPicker();
|
||||
openPicker();
|
||||
setDesignerTheme(selectedTheme);
|
||||
setDesignerTheme(designerTheme);
|
||||
};
|
||||
|
||||
const randomColor = (withAlpha?: boolean) => {
|
||||
@@ -185,6 +162,20 @@ export function ThemeEditor({
|
||||
return color;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (font) {
|
||||
setDesignerTheme({
|
||||
...designerTheme,
|
||||
themeFont: font,
|
||||
});
|
||||
}
|
||||
}, [font]);
|
||||
useEffect(() => {
|
||||
if (selectedTheme) {
|
||||
setCustomFontEnabled(designerTheme.themeFont !== null);
|
||||
setFont(designerTheme.themeFont);
|
||||
}
|
||||
}, [selectedTheme]);
|
||||
return (
|
||||
<>
|
||||
<Group p={'2rem'} w={'100%'} justify='space-between'>
|
||||
@@ -197,10 +188,10 @@ export function ThemeEditor({
|
||||
>
|
||||
<ColorSwatch
|
||||
onClick={() => {
|
||||
handleSwatchClick('primaryColor', selectedTheme.primaryColor);
|
||||
handleSwatchClick('primaryColor', designerTheme.primaryColor);
|
||||
}}
|
||||
color={selectedTheme.primaryColor}
|
||||
style={{ borderColor: selectedTheme.primaryColor }}
|
||||
color={designerTheme.primaryColor}
|
||||
style={{ borderColor: designerTheme.primaryColor }}
|
||||
className={colorSwatchClasses.themeDesignerSwatch}
|
||||
classNames={colorSwatchClasses}
|
||||
top={'11.5rem'}
|
||||
@@ -214,10 +205,10 @@ export function ThemeEditor({
|
||||
>
|
||||
<ColorSwatch
|
||||
onClick={() => {
|
||||
handleSwatchClick('accentColor', selectedTheme.accentColor);
|
||||
handleSwatchClick('accentColor', designerTheme.accentColor);
|
||||
}}
|
||||
color={selectedTheme.accentColor}
|
||||
style={{ borderColor: selectedTheme.primaryColor }}
|
||||
color={designerTheme.accentColor}
|
||||
style={{ borderColor: designerTheme.primaryColor }}
|
||||
className={colorSwatchClasses.themeDesignerSwatch}
|
||||
classNames={colorSwatchClasses}
|
||||
bottom={'6rem'}
|
||||
@@ -231,10 +222,10 @@ export function ThemeEditor({
|
||||
>
|
||||
<ColorSwatch
|
||||
onClick={() => {
|
||||
handleSwatchClick('backgroundColor', selectedTheme.backgroundColor);
|
||||
handleSwatchClick('backgroundColor', designerTheme.backgroundColor);
|
||||
}}
|
||||
color={selectedTheme.backgroundColor}
|
||||
style={{ borderColor: selectedTheme.primaryColor }}
|
||||
color={designerTheme.backgroundColor}
|
||||
style={{ borderColor: designerTheme.primaryColor }}
|
||||
className={colorSwatchClasses.themeDesignerSwatch}
|
||||
classNames={colorSwatchClasses}
|
||||
bottom={'4rem'}
|
||||
@@ -248,10 +239,10 @@ export function ThemeEditor({
|
||||
>
|
||||
<ColorSwatch
|
||||
onClick={() => {
|
||||
handleSwatchClick('borderColor', selectedTheme.borderColor);
|
||||
handleSwatchClick('borderColor', designerTheme.borderColor);
|
||||
}}
|
||||
color={selectedTheme.borderColor}
|
||||
style={{ borderColor: selectedTheme.primaryColor }}
|
||||
color={designerTheme.borderColor}
|
||||
style={{ borderColor: designerTheme.primaryColor }}
|
||||
className={colorSwatchClasses.themeDesignerSwatch}
|
||||
classNames={colorSwatchClasses}
|
||||
top={'4.5rem'}
|
||||
@@ -265,10 +256,10 @@ export function ThemeEditor({
|
||||
>
|
||||
<ColorSwatch
|
||||
onClick={() => {
|
||||
handleSwatchClick('searchColor', selectedTheme.searchColor);
|
||||
handleSwatchClick('searchColor', designerTheme.searchColor);
|
||||
}}
|
||||
color={selectedTheme.searchColor}
|
||||
style={{ borderColor: selectedTheme.primaryColor }}
|
||||
color={designerTheme.searchColor}
|
||||
style={{ borderColor: designerTheme.primaryColor }}
|
||||
className={colorSwatchClasses.themeDesignerSwatch}
|
||||
classNames={colorSwatchClasses}
|
||||
top={'3.25rem'}
|
||||
@@ -284,13 +275,13 @@ export function ThemeEditor({
|
||||
onClick={() => {
|
||||
closePicker();
|
||||
openBackgroundPicker();
|
||||
setDesignerTheme(selectedTheme);
|
||||
setDesignerTheme(designerTheme);
|
||||
}}
|
||||
pos={'absolute'}
|
||||
right={0}
|
||||
style={{
|
||||
color: selectedTheme.backgroundColor,
|
||||
backgroundColor: selectedTheme.primaryColor,
|
||||
color: designerTheme.backgroundColor,
|
||||
backgroundColor: designerTheme.primaryColor,
|
||||
borderRadius: 0,
|
||||
borderBottomLeftRadius: 10,
|
||||
borderTopRightRadius: 10,
|
||||
@@ -364,7 +355,7 @@ export function ThemeEditor({
|
||||
const rc = randomColor(colorId === 'searchColor');
|
||||
setColorValue(rc);
|
||||
setDesignerTheme({
|
||||
...selectedTheme,
|
||||
...designerTheme,
|
||||
[colorId]: rc,
|
||||
});
|
||||
}}
|
||||
@@ -374,8 +365,8 @@ export function ThemeEditor({
|
||||
<Button
|
||||
color={'green'}
|
||||
onClick={() => {
|
||||
setSelectedTheme({
|
||||
...selectedTheme,
|
||||
setDesignerTheme({
|
||||
...designerTheme,
|
||||
[colorId]: colorValue,
|
||||
});
|
||||
|
||||
@@ -391,7 +382,7 @@ export function ThemeEditor({
|
||||
closePicker();
|
||||
setDesignerTheme({
|
||||
...designerTheme,
|
||||
[colorId]: selectedTheme[colorId as keyof Theme],
|
||||
[colorId]: designerTheme[colorId as keyof Theme],
|
||||
});
|
||||
}}
|
||||
>
|
||||
@@ -411,8 +402,8 @@ export function ThemeEditor({
|
||||
color: 'var(--mantine-color-primary-0)',
|
||||
},
|
||||
input: {
|
||||
color: selectedTheme.primaryColor,
|
||||
backgroundColor: selectedTheme.backgroundColor,
|
||||
color: designerTheme.primaryColor,
|
||||
backgroundColor: designerTheme.backgroundColor,
|
||||
border: 'none',
|
||||
borderBottom: '1px solid var(--mantine-color-primary-0)',
|
||||
},
|
||||
@@ -478,8 +469,8 @@ export function ThemeEditor({
|
||||
<Button
|
||||
color={'green'}
|
||||
onClick={() => {
|
||||
setSelectedTheme({
|
||||
...selectedTheme,
|
||||
setDesignerTheme({
|
||||
...designerTheme,
|
||||
backgroundImage: designerTheme.backgroundImage,
|
||||
});
|
||||
closeBackgroundPicker();
|
||||
@@ -494,7 +485,7 @@ export function ThemeEditor({
|
||||
closeBackgroundPicker();
|
||||
setDesignerTheme({
|
||||
...designerTheme,
|
||||
backgroundImage: selectedTheme.backgroundImage,
|
||||
backgroundImage: designerTheme.backgroundImage,
|
||||
});
|
||||
}}
|
||||
>
|
||||
@@ -509,17 +500,17 @@ export function ThemeEditor({
|
||||
<Group gap={2} w={'100%'} justify='space-between' align='center'>
|
||||
<Checkbox.Card
|
||||
w={'calc(50% - 1px)'}
|
||||
checked={selectedTheme.textShadowsEnabled === 1}
|
||||
checked={designerTheme.textShadowsEnabled === 1}
|
||||
c={'var(--mantine-color-background-0)'}
|
||||
onChange={(e) => {
|
||||
setSelectedTheme({
|
||||
...selectedTheme,
|
||||
setDesignerTheme({
|
||||
...designerTheme,
|
||||
textShadowsEnabled: e ? 1 : 0,
|
||||
});
|
||||
}}
|
||||
style={{
|
||||
border: 'none',
|
||||
filter: `grayscale(${selectedTheme.textShadowsEnabled === 1 ? 0 : '75%'}) brightness(${selectedTheme.textShadowsEnabled === 1 ? '1' : '1.5'})`,
|
||||
filter: `grayscale(${designerTheme.textShadowsEnabled === 1 ? 0 : '75%'}) brightness(${designerTheme.textShadowsEnabled === 1 ? '1' : '1.5'})`,
|
||||
transition: 'all 1s ease',
|
||||
}}
|
||||
>
|
||||
@@ -532,15 +523,15 @@ export function ThemeEditor({
|
||||
w={'100%'}
|
||||
justify='center'
|
||||
style={{
|
||||
backgroundColor: selectedTheme.backgroundColor,
|
||||
backgroundColor: designerTheme.backgroundColor,
|
||||
}}
|
||||
>
|
||||
<Text
|
||||
classNames={textClasses}
|
||||
className={textClasses.sectionTitle}
|
||||
style={{
|
||||
color: selectedTheme.accentColor,
|
||||
textShadow: `2px 2px ${selectedTheme.primaryColor}`,
|
||||
color: designerTheme.accentColor,
|
||||
textShadow: `2px 2px ${designerTheme.primaryColor}`,
|
||||
}}
|
||||
>
|
||||
Shadows
|
||||
@@ -550,17 +541,17 @@ export function ThemeEditor({
|
||||
</Checkbox.Card>
|
||||
<Checkbox.Card
|
||||
w={'calc(50% - 1px)'}
|
||||
checked={selectedTheme.appShadowsEnabled === 1}
|
||||
checked={designerTheme.appShadowsEnabled === 1}
|
||||
c={'var(--mantine-color-background-0)'}
|
||||
onChange={(e) => {
|
||||
setSelectedTheme({
|
||||
...selectedTheme,
|
||||
setDesignerTheme({
|
||||
...designerTheme,
|
||||
appShadowsEnabled: e ? 1 : 0,
|
||||
});
|
||||
}}
|
||||
style={{
|
||||
border: 'none',
|
||||
filter: `grayscale(${selectedTheme.appShadowsEnabled === 1 ? 0 : '75%'}) brightness(${selectedTheme.appShadowsEnabled === 1 ? '1' : '1.5'})`,
|
||||
filter: `grayscale(${designerTheme.appShadowsEnabled === 1 ? 0 : '75%'}) brightness(${designerTheme.appShadowsEnabled === 1 ? '1' : '1.5'})`,
|
||||
transition: 'all 1s ease',
|
||||
}}
|
||||
>
|
||||
@@ -574,7 +565,7 @@ export function ThemeEditor({
|
||||
justify='center'
|
||||
align='center'
|
||||
style={{
|
||||
backgroundColor: selectedTheme.backgroundColor,
|
||||
backgroundColor: designerTheme.backgroundColor,
|
||||
overflow: 'clip',
|
||||
}}
|
||||
>
|
||||
@@ -582,10 +573,10 @@ export function ThemeEditor({
|
||||
style={{
|
||||
marginTop: '12px',
|
||||
marginBottom: '7px',
|
||||
color: selectedTheme.primaryColor,
|
||||
color: designerTheme.primaryColor,
|
||||
height: 32,
|
||||
width: 32,
|
||||
filter: `drop-shadow(2px 2px color-mix(in srgb, ${selectedTheme.accentColor}, transparent 30%))`,
|
||||
filter: `drop-shadow(2px 2px color-mix(in srgb, ${designerTheme.accentColor}, transparent 30%))`,
|
||||
}}
|
||||
/>
|
||||
</Group>
|
||||
@@ -603,7 +594,7 @@ export function ThemeEditor({
|
||||
size={32}
|
||||
onClick={() => {
|
||||
setCustomFontEnabled(!customFontEnabled);
|
||||
setFont(null);
|
||||
setFont(customFontEnabled ? defaultTheme.themeFont : null);
|
||||
}}
|
||||
style={{
|
||||
borderRadius: '0px',
|
||||
@@ -627,15 +618,13 @@ export function ThemeEditor({
|
||||
<FontPicker
|
||||
autoLoad
|
||||
defaultValue={
|
||||
selectedTheme.themeFont === null
|
||||
? 'Jost'
|
||||
: selectedTheme.themeFont
|
||||
designerTheme.themeFont === null
|
||||
? currentUser.defaultFont
|
||||
: designerTheme.themeFont
|
||||
}
|
||||
value={(font: string) => {
|
||||
value={(pickerFont: string) => {
|
||||
if (customFontEnabled) {
|
||||
setFont(font);
|
||||
} else {
|
||||
setFont(null);
|
||||
setFont(pickerFont);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
@@ -650,7 +639,7 @@ export function ThemeEditor({
|
||||
color={'red'}
|
||||
size={32}
|
||||
onClick={() => {
|
||||
setFont(null);
|
||||
setFont(currentUser.defaultFont);
|
||||
setCustomFontEnabled(false);
|
||||
}}
|
||||
style={{
|
||||
@@ -662,7 +651,7 @@ export function ThemeEditor({
|
||||
</Tooltip>
|
||||
</Group>
|
||||
</Stack>
|
||||
{JSON.stringify(defaultTheme) !== JSON.stringify(selectedTheme) && (
|
||||
{JSON.stringify(defaultTheme) !== JSON.stringify(designerTheme) && (
|
||||
<Stack
|
||||
gap={0}
|
||||
w={'95%'}
|
||||
@@ -703,276 +692,292 @@ export function ThemeEditor({
|
||||
Object.keys(getObjectDiff(defaultTheme, designerTheme)).map(
|
||||
(key: any) => {
|
||||
return (
|
||||
<Stack
|
||||
w={'100%'}
|
||||
align='center'
|
||||
justify='center'
|
||||
gap={0}
|
||||
key={key}
|
||||
>
|
||||
<Group w={'100%'} justify='space-between'>
|
||||
<Text
|
||||
key={key}
|
||||
pl={2}
|
||||
style={{
|
||||
color: 'var(--mantine-color-primary-0)',
|
||||
backgroundColor:
|
||||
'var(--mantine-color-background-0)',
|
||||
}}
|
||||
>
|
||||
{ThemeProperties[key as keyof typeof ThemeProperties]}
|
||||
</Text>
|
||||
<Tooltip
|
||||
label={`Reset ${
|
||||
ThemeProperties[key as keyof typeof ThemeProperties]
|
||||
}`}
|
||||
classNames={toolTipClasses}
|
||||
className={toolTipClasses.default}
|
||||
>
|
||||
<ActionIcon
|
||||
variant='subtle'
|
||||
color='red'
|
||||
onClick={() => {
|
||||
setSelectedTheme({
|
||||
...designerTheme,
|
||||
[key]: defaultTheme[key as keyof Theme],
|
||||
});
|
||||
if (key.includes('Font')) {
|
||||
setFont(defaultTheme.themeFont);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<FiX />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
{key === 'name' && (
|
||||
<Group
|
||||
w={'100%'}
|
||||
justify='center'
|
||||
bg='var(--mantine-color-accent-0)'
|
||||
style={{ borderRadius: 8, overflow: 'clip' }}
|
||||
h={48}
|
||||
>
|
||||
<Text>{defaultTheme[key as keyof Theme]}</Text>
|
||||
<Text>→</Text>
|
||||
<Text>{designerTheme[key as keyof Theme]}</Text>
|
||||
</Group>
|
||||
)}
|
||||
{key.includes('Shadow') && (
|
||||
<Group
|
||||
w={'100%'}
|
||||
justify='center'
|
||||
bg='var(--mantine-color-accent-0)'
|
||||
style={{ borderRadius: 8, overflow: 'clip' }}
|
||||
h={48}
|
||||
>
|
||||
{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>
|
||||
)}
|
||||
{key.includes('Font') && (
|
||||
<Group
|
||||
w={'100%'}
|
||||
justify='center'
|
||||
bg='var(--mantine-color-accent-0)'
|
||||
h={48}
|
||||
style={{ borderRadius: 8, overflow: 'clip' }}
|
||||
>
|
||||
key !== 'id' && (
|
||||
<Stack
|
||||
w={'100%'}
|
||||
align='center'
|
||||
justify='center'
|
||||
gap={0}
|
||||
key={key}
|
||||
>
|
||||
<Group w={'100%'} justify='space-between'>
|
||||
<Text
|
||||
key={key}
|
||||
pl={2}
|
||||
style={{
|
||||
fontFamily:
|
||||
(defaultTheme[key as keyof Theme] as string) ??
|
||||
undefined,
|
||||
fontSize: 18,
|
||||
color: 'var(--mantine-color-primary-0)',
|
||||
backgroundColor:
|
||||
'var(--mantine-color-background-0)',
|
||||
}}
|
||||
>
|
||||
{defaultTheme[key as keyof Theme] ||
|
||||
`Default (${currentUser.defaultFont})`}
|
||||
</Text>
|
||||
<Text>→</Text>
|
||||
<Text
|
||||
style={{
|
||||
fontFamily: selectedTheme.themeFont ?? undefined,
|
||||
fontSize: 18,
|
||||
}}
|
||||
>
|
||||
{designerTheme[key as keyof Theme] ||
|
||||
`Default (${currentUser.defaultFont})`}
|
||||
</Text>
|
||||
</Group>
|
||||
)}
|
||||
{key === 'backgroundImage' && (
|
||||
<Group
|
||||
w={'100%'}
|
||||
justify='center'
|
||||
gap={4}
|
||||
bg='var(--mantine-color-accent-0)'
|
||||
style={{ borderRadius: 8, overflow: 'clip' }}
|
||||
>
|
||||
<Image
|
||||
w={'40%'}
|
||||
src={
|
||||
(
|
||||
defaultTheme[key as keyof Theme] as string
|
||||
).toLocaleLowerCase() === 'none'
|
||||
? 'https://placehold.co/540x360?text=None'
|
||||
: `../../api/backgroundImages/thumbs/${defaultTheme[key as keyof Theme] as string}`
|
||||
{
|
||||
ThemeProperties[
|
||||
key as keyof typeof ThemeProperties
|
||||
]
|
||||
}
|
||||
/>
|
||||
<Text>→</Text>
|
||||
<Image
|
||||
w={'40%'}
|
||||
src={
|
||||
(
|
||||
designerTheme[key as keyof Theme] as string
|
||||
).toLocaleLowerCase() === 'none'
|
||||
? 'https://placehold.co/540x360?text=None'
|
||||
: `../../api/backgroundImages/thumbs/${designerTheme[key as keyof Theme] as string}`
|
||||
}
|
||||
/>
|
||||
</Group>
|
||||
)}
|
||||
{key.includes('Color') && (
|
||||
<Group
|
||||
w={'100%'}
|
||||
justify='space-between'
|
||||
bg='var(--mantine-color-accent-0)'
|
||||
style={{ borderRadius: 8, overflow: 'clip' }}
|
||||
>
|
||||
</Text>
|
||||
<Tooltip
|
||||
label='Copy color code'
|
||||
label={`Reset ${
|
||||
ThemeProperties[
|
||||
key as keyof typeof ThemeProperties
|
||||
]
|
||||
}`}
|
||||
classNames={toolTipClasses}
|
||||
className={toolTipClasses.default}
|
||||
>
|
||||
<ColorSwatch
|
||||
h={50}
|
||||
<ActionIcon
|
||||
variant='subtle'
|
||||
color='red'
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(
|
||||
defaultTheme[key as keyof Theme] as string,
|
||||
);
|
||||
notifications.show({
|
||||
title: (
|
||||
<Text
|
||||
fw={600}
|
||||
c={'var(--mantine-color-accent-0)'}
|
||||
>
|
||||
Copied{' '}
|
||||
{
|
||||
ThemeProperties[
|
||||
key as keyof typeof ThemeProperties
|
||||
]
|
||||
}
|
||||
</Text>
|
||||
),
|
||||
message: (
|
||||
<Text c={'var(--mantine-color-primary-0)'}>
|
||||
{
|
||||
defaultTheme[
|
||||
key as keyof Theme
|
||||
] as string
|
||||
}
|
||||
</Text>
|
||||
),
|
||||
autoClose: true,
|
||||
withCloseButton: true,
|
||||
icon: <FaClipboard size={24} />,
|
||||
setDesignerTheme({
|
||||
...designerTheme,
|
||||
[key]: defaultTheme[key as keyof Theme],
|
||||
});
|
||||
if (key.includes('Font')) {
|
||||
setFont(defaultTheme.themeFont);
|
||||
}
|
||||
}}
|
||||
color={defaultTheme[key as keyof Theme] as string}
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
styles={{
|
||||
alphaOverlay: {
|
||||
borderRadius: '0px',
|
||||
},
|
||||
colorOverlay: {
|
||||
borderRadius: '0px',
|
||||
},
|
||||
shadowOverlay: {
|
||||
borderRadius: '0px',
|
||||
},
|
||||
childrenOverlay: {
|
||||
borderRadius: '0px',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Text>→</Text>
|
||||
<Tooltip
|
||||
label='Copy color code'
|
||||
classNames={toolTipClasses}
|
||||
className={toolTipClasses.default}
|
||||
>
|
||||
<ColorSwatch
|
||||
h={50}
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(
|
||||
defaultTheme[key as keyof Theme] as string,
|
||||
);
|
||||
notifications.show({
|
||||
title: (
|
||||
<Text
|
||||
fw={600}
|
||||
c={'var(--mantine-color-accent-0)'}
|
||||
>
|
||||
Copied{' '}
|
||||
{
|
||||
ThemeProperties[
|
||||
key as keyof typeof ThemeProperties
|
||||
]
|
||||
}
|
||||
</Text>
|
||||
),
|
||||
message: (
|
||||
<Text c={'var(--mantine-color-primary-0)'}>
|
||||
{
|
||||
designerTheme[
|
||||
key as keyof Theme
|
||||
] as string
|
||||
}
|
||||
</Text>
|
||||
),
|
||||
autoClose: true,
|
||||
withCloseButton: true,
|
||||
icon: <FaClipboard size={24} />,
|
||||
});
|
||||
}}
|
||||
color={
|
||||
designerTheme[key as keyof Theme] as string
|
||||
}
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
styles={{
|
||||
alphaOverlay: {
|
||||
borderRadius: '0px',
|
||||
},
|
||||
colorOverlay: {
|
||||
borderRadius: '0px',
|
||||
},
|
||||
shadowOverlay: {
|
||||
borderRadius: '0px',
|
||||
},
|
||||
childrenOverlay: {
|
||||
borderRadius: '0px',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
>
|
||||
<FiX />
|
||||
</ActionIcon>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
)}
|
||||
</Stack>
|
||||
{key === 'name' && (
|
||||
<Group
|
||||
w={'100%'}
|
||||
justify='center'
|
||||
bg='var(--mantine-color-accent-0)'
|
||||
style={{ borderRadius: 8, overflow: 'clip' }}
|
||||
h={48}
|
||||
>
|
||||
<Text>{defaultTheme[key as keyof Theme]}</Text>
|
||||
<Text>→</Text>
|
||||
<Text>{designerTheme[key as keyof Theme]}</Text>
|
||||
</Group>
|
||||
)}
|
||||
{key.includes('Shadow') && (
|
||||
<Group
|
||||
w={'100%'}
|
||||
justify='center'
|
||||
bg='var(--mantine-color-accent-0)'
|
||||
style={{ borderRadius: 8, overflow: 'clip' }}
|
||||
h={48}
|
||||
>
|
||||
{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>
|
||||
)}
|
||||
{key.includes('Font') && (
|
||||
<Group
|
||||
w={'100%'}
|
||||
justify='center'
|
||||
bg='var(--mantine-color-accent-0)'
|
||||
h={48}
|
||||
style={{ borderRadius: 8, overflow: 'clip' }}
|
||||
>
|
||||
<Text
|
||||
style={{
|
||||
fontFamily:
|
||||
(defaultTheme[
|
||||
key as keyof Theme
|
||||
] as string) ?? undefined,
|
||||
fontSize: 18,
|
||||
}}
|
||||
>
|
||||
{defaultTheme[key as keyof Theme] ||
|
||||
`Default (${currentUser.defaultFont})`}
|
||||
</Text>
|
||||
<Text>→</Text>
|
||||
<Text
|
||||
style={{
|
||||
fontFamily:
|
||||
designerTheme.themeFont ?? undefined,
|
||||
fontSize: 18,
|
||||
}}
|
||||
>
|
||||
{designerTheme[key as keyof Theme] ||
|
||||
`Default (${currentUser.defaultFont})`}
|
||||
</Text>
|
||||
</Group>
|
||||
)}
|
||||
{key === 'backgroundImage' && (
|
||||
<Group
|
||||
w={'100%'}
|
||||
justify='center'
|
||||
gap={4}
|
||||
bg='var(--mantine-color-accent-0)'
|
||||
style={{ borderRadius: 8, overflow: 'clip' }}
|
||||
>
|
||||
<Image
|
||||
w={'40%'}
|
||||
src={
|
||||
(
|
||||
defaultTheme[key as keyof Theme] as string
|
||||
).toLocaleLowerCase() === 'none'
|
||||
? 'https://placehold.co/540x360?text=None'
|
||||
: `../../api/backgroundImages/thumbs/${defaultTheme[key as keyof Theme] as string}`
|
||||
}
|
||||
/>
|
||||
<Text>→</Text>
|
||||
<Image
|
||||
w={'40%'}
|
||||
src={
|
||||
(
|
||||
designerTheme[key as keyof Theme] as string
|
||||
).toLocaleLowerCase() === 'none'
|
||||
? 'https://placehold.co/540x360?text=None'
|
||||
: `../../api/backgroundImages/thumbs/${designerTheme[key as keyof Theme] as string}`
|
||||
}
|
||||
/>
|
||||
</Group>
|
||||
)}
|
||||
{key.includes('Color') && (
|
||||
<Group
|
||||
w={'100%'}
|
||||
justify='space-between'
|
||||
bg='var(--mantine-color-accent-0)'
|
||||
style={{ borderRadius: 8, overflow: 'clip' }}
|
||||
>
|
||||
<Tooltip
|
||||
label='Copy color code'
|
||||
classNames={toolTipClasses}
|
||||
className={toolTipClasses.default}
|
||||
>
|
||||
<ColorSwatch
|
||||
h={50}
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(
|
||||
defaultTheme[key as keyof Theme] as string,
|
||||
);
|
||||
notifications.show({
|
||||
title: (
|
||||
<Text
|
||||
fw={600}
|
||||
c={'var(--mantine-color-accent-0)'}
|
||||
>
|
||||
Copied{' '}
|
||||
{
|
||||
ThemeProperties[
|
||||
key as keyof typeof ThemeProperties
|
||||
]
|
||||
}
|
||||
</Text>
|
||||
),
|
||||
message: (
|
||||
<Text
|
||||
c={'var(--mantine-color-primary-0)'}
|
||||
>
|
||||
{
|
||||
defaultTheme[
|
||||
key as keyof Theme
|
||||
] as string
|
||||
}
|
||||
</Text>
|
||||
),
|
||||
autoClose: true,
|
||||
withCloseButton: true,
|
||||
icon: <FaClipboard size={24} />,
|
||||
});
|
||||
}}
|
||||
color={
|
||||
defaultTheme[key as keyof Theme] as string
|
||||
}
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
styles={{
|
||||
alphaOverlay: {
|
||||
borderRadius: '0px',
|
||||
},
|
||||
colorOverlay: {
|
||||
borderRadius: '0px',
|
||||
},
|
||||
shadowOverlay: {
|
||||
borderRadius: '0px',
|
||||
},
|
||||
childrenOverlay: {
|
||||
borderRadius: '0px',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
<Text>→</Text>
|
||||
<Tooltip
|
||||
label='Copy color code'
|
||||
classNames={toolTipClasses}
|
||||
className={toolTipClasses.default}
|
||||
>
|
||||
<ColorSwatch
|
||||
h={50}
|
||||
onClick={() => {
|
||||
navigator.clipboard.writeText(
|
||||
defaultTheme[key as keyof Theme] as string,
|
||||
);
|
||||
notifications.show({
|
||||
title: (
|
||||
<Text
|
||||
fw={600}
|
||||
c={'var(--mantine-color-accent-0)'}
|
||||
>
|
||||
Copied{' '}
|
||||
{
|
||||
ThemeProperties[
|
||||
key as keyof typeof ThemeProperties
|
||||
]
|
||||
}
|
||||
</Text>
|
||||
),
|
||||
message: (
|
||||
<Text
|
||||
c={'var(--mantine-color-primary-0)'}
|
||||
>
|
||||
{
|
||||
designerTheme[
|
||||
key as keyof Theme
|
||||
] as string
|
||||
}
|
||||
</Text>
|
||||
),
|
||||
autoClose: true,
|
||||
withCloseButton: true,
|
||||
icon: <FaClipboard size={24} />,
|
||||
});
|
||||
}}
|
||||
color={
|
||||
designerTheme[key as keyof Theme] as string
|
||||
}
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
styles={{
|
||||
alphaOverlay: {
|
||||
borderRadius: '0px',
|
||||
},
|
||||
colorOverlay: {
|
||||
borderRadius: '0px',
|
||||
},
|
||||
shadowOverlay: {
|
||||
borderRadius: '0px',
|
||||
},
|
||||
childrenOverlay: {
|
||||
borderRadius: '0px',
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</Group>
|
||||
)}
|
||||
</Stack>
|
||||
)
|
||||
);
|
||||
},
|
||||
)}
|
||||
@@ -988,8 +993,8 @@ export function ThemeEditor({
|
||||
>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setSelectedTheme({
|
||||
...selectedTheme,
|
||||
setDesignerTheme({
|
||||
...designerTheme,
|
||||
backgroundColor: randomColor(),
|
||||
searchColor: randomColor(true),
|
||||
primaryColor: randomColor(),
|
||||
@@ -1003,12 +1008,13 @@ export function ThemeEditor({
|
||||
</Tooltip>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setCustomFontEnabled(defaultTheme.themeFont !== null);
|
||||
duplicate
|
||||
? setSelectedTheme({
|
||||
? setDesignerTheme({
|
||||
...defaultTheme,
|
||||
name: `${defaultTheme.name} copy`,
|
||||
})
|
||||
: setSelectedTheme({ ...defaultTheme });
|
||||
: setDesignerTheme({ ...defaultTheme });
|
||||
}}
|
||||
>
|
||||
Reset Changes
|
||||
@@ -1020,7 +1026,7 @@ export function ThemeEditor({
|
||||
</Group>
|
||||
<Group>
|
||||
<Button
|
||||
disabled={JSON.stringify(defaultTheme) === JSON.stringify(selectedTheme)}
|
||||
disabled={JSON.stringify(defaultTheme) === JSON.stringify(designerTheme)}
|
||||
className={buttonClasses.saveButton}
|
||||
classNames={buttonClasses}
|
||||
onClick={handleSaveTheme}
|
||||
|
||||
Reference in New Issue
Block a user