diff --git a/src/contexts/theme.ts b/src/contexts/theme.ts index 2259263..8107e32 100644 --- a/src/contexts/theme.ts +++ b/src/contexts/theme.ts @@ -9,6 +9,9 @@ const appTheme = atom({ primaryColor: '#222222', accentColor: '#5c5c5c', borderColor: '#5c5c5c', + textShadowsEnabled: false, + appShadowsEnabled: false, + themeFont: null, }); export { appTheme }; diff --git a/src/hooks/useCommonHooks.ts b/src/hooks/useCommonHooks.ts index 2e01f15..13c90e6 100644 --- a/src/hooks/useCommonHooks.ts +++ b/src/hooks/useCommonHooks.ts @@ -95,6 +95,7 @@ export function useCommonHooks() { nickname: 'Boss', email: 'triggerUser@default.com', physicalAddress: '1510 Polk St, Houston, TX 77002', + defaultFont: 'Jost', }, }); const [currentLocation, setCurrentLocation] = useLocalStorage({ diff --git a/src/pages/homepage/components/Search/Search.tsx b/src/pages/homepage/components/Search/Search.tsx index 0e9e93e..80fa286 100644 --- a/src/pages/homepage/components/Search/Search.tsx +++ b/src/pages/homepage/components/Search/Search.tsx @@ -179,6 +179,8 @@ export default function Search({ open(`${providerURL}${subtext}`, '_self'); }); } else if (providerLabel === 'Show weather') { + setSearchValue(''); + closeDropdown(); openWeatherModal(); } else if (providerLabel.startsWith('Launch')) { const url = applications?.find((app: Application) => diff --git a/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeEditor.tsx b/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeEditor.tsx index fa06bb5..0d422af 100644 --- a/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeEditor.tsx +++ b/src/pages/settings/components/Theming/Themes/ThemeModal/components/ThemeEditor.tsx @@ -1,11 +1,13 @@ import { ActionIcon, + Box, Button, Checkbox, ColorPicker, ColorSwatch, Group, Image, + Overlay, ScrollArea, Stack, Text, @@ -14,9 +16,11 @@ import { UnstyledButton, } from '@mantine/core'; import { useDisclosure } from '@mantine/hooks'; +import { notifications } from '@mantine/notifications'; import { useCommonHooks } from 'hooks'; import { useEffect, useRef, useState } from 'react'; import FontPicker from 'react-fontpicker-ts'; +import { FaClipboard, FaFont, FaGoogle } from 'react-icons/fa'; import { FaShuffle } from 'react-icons/fa6'; import { FiImage, FiSave, FiShuffle, FiX } from 'react-icons/fi'; import { @@ -27,7 +31,7 @@ import { textInputClasses, toolTipClasses, } from 'styles'; -import { BackgroundProperties, type Theme } from 'types'; +import { type Theme, ThemeProperties } from 'types'; import { ThemeModalContent } from './ThemeModalContent'; export function ThemeEditor({ @@ -61,31 +65,40 @@ export function ThemeEditor({ }) { const [query, setQuery] = useState(''); const [hovered, setHovered] = useState(-1); - const { isMobile, theme, getObjectDiff, textShadowStyle } = useCommonHooks(); + const { currentUser, isMobile, theme, getObjectDiff, textShadowStyle } = + useCommonHooks(); const viewportRef = useRef(null); const [colorId, setColorId] = useState(''); const [colorValue, setColorValue] = useState('#000000'); const [font, setFont] = useState(); + const [customFontEnabled, setCustomFontEnabled] = useState(false); const re = /(?:\.([^.]+))?$/; const [backgroundPicker, { open: openBackgroundPicker, close: closeBackgroundPicker }] = useDisclosure(false); 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 ( @@ -289,10 +303,10 @@ export function ThemeEditor({ {pickerOpen && ( @@ -305,8 +319,7 @@ export function ThemeEditor({ textShadow: theme.textShadowsEnabled ? textShadowStyle : undefined, }} > - Change{' '} - {BackgroundProperties[colorId as keyof typeof BackgroundProperties]} + Change {ThemeProperties[colorId as keyof typeof ThemeProperties]} {colorId === 'searchColor' && ( - - { - setSelectedTheme({ - ...selectedTheme, - textShadowsEnabled: e.target.checked ? 1 : 0, - }); - }} - styles={{ - root: { width: '50%' }, - body: { - width: '100%', - display: 'flex', - justifyContent: 'space-between', - }, - }} - /> - { - setSelectedTheme({ - ...selectedTheme, - appShadowsEnabled: e.target.checked ? 1 : 0, - }); - }} - styles={{ - root: { width: '50%' }, - body: { - width: '100%', - display: 'flex', - justifyContent: 'space-between', - }, - }} - /> - - setFont(font)} - /> - { - setFont(null); + + + { + setSelectedTheme({ + ...selectedTheme, + textShadowsEnabled: e ? 1 : 0, + }); + }} + style={{ + border: 'none', + filter: `grayscale(${selectedTheme.textShadowsEnabled === 1 ? 0 : '75%'}) brightness(${selectedTheme.textShadowsEnabled === 1 ? '1' : '1.5'})`, + transition: 'all 1s ease', }} > - - + + + + Shadows + + + + + { + setSelectedTheme({ + ...selectedTheme, + appShadowsEnabled: e ? 1 : 0, + }); + }} + style={{ + border: 'none', + filter: `grayscale(${selectedTheme.appShadowsEnabled === 1 ? 0 : '75%'}) brightness(${selectedTheme.appShadowsEnabled === 1 ? '1' : '1.5'})`, + transition: 'all 1s ease', + }} + > + + + + + + + + + + { + setCustomFontEnabled(!customFontEnabled); + setFont(null); + }} + style={{ + borderRadius: '0px', + filter: `grayscale(${customFontEnabled ? 0 : '75%'})`, + }} + > + + + + { + if (!customFontEnabled) { + e.preventDefault(); + e.stopPropagation(); + } + }} + pos={'relative'} + > + {!customFontEnabled && } + { + if (customFontEnabled) { + setFont(font); + } else { + setFont(null); + } + }} + /> + + + { + setFont(null); + setCustomFontEnabled(false); + }} + style={{ + borderRadius: '0px', + }} + > + + + {JSON.stringify(defaultTheme) !== JSON.stringify(selectedTheme) && ( - <> - - Changes: + + + Changes - + {getObjectDiff(defaultTheme, designerTheme) !== null && Object.keys(getObjectDiff(defaultTheme, designerTheme)).map( (key: any) => { @@ -576,22 +710,115 @@ export function ThemeEditor({ gap={0} key={key} > - - { - BackgroundProperties[ - key as keyof typeof BackgroundProperties - ] - } - + + + {ThemeProperties[key as keyof typeof ThemeProperties]} + + + { + setSelectedTheme({ + ...designerTheme, + [key]: defaultTheme[key as keyof Theme], + }); + if (key.includes('Font')) { + setFont(defaultTheme.themeFont); + } + }} + > + + + + {key === 'name' && ( - + {defaultTheme[key as keyof Theme]} → {designerTheme[key as keyof Theme]} )} + {key.includes('Shadow') && ( + + {defaultTheme[key as keyof Theme] === 0 ? ( + Off + ) : ( + On + )} + → + {designerTheme[key as keyof Theme] === 0 ? ( + Off + ) : ( + On + )} + + )} + {key.includes('Font') && ( + + + {defaultTheme[key as keyof Theme] || + `Default (${currentUser.defaultFont})`} + + → + + {designerTheme[key as keyof Theme] || + `Default (${currentUser.defaultFont})`} + + + )} {key === 'backgroundImage' && ( - + )} {key.includes('Color') && ( - - + + + { + navigator.clipboard.writeText( + defaultTheme[key as keyof Theme] as string, + ); + notifications.show({ + title: ( + + Copied{' '} + { + ThemeProperties[ + key as keyof typeof ThemeProperties + ] + } + + ), + message: ( + + { + defaultTheme[ + key as keyof Theme + ] as string + } + + ), + autoClose: true, + withCloseButton: true, + icon: , + }); + }} + color={defaultTheme[key as keyof Theme] as string} + style={{ + cursor: 'pointer', + }} + styles={{ + alphaOverlay: { + borderRadius: '0px', + }, + colorOverlay: { + borderRadius: '0px', + }, + shadowOverlay: { + borderRadius: '0px', + }, + childrenOverlay: { + borderRadius: '0px', + }, + }} + /> + → - - - )} - {key.includes('Shadow') && ( - - {defaultTheme[key as keyof Theme] === 0 ? ( - Off - ) : ( - On - )} - → - {designerTheme[key as keyof Theme] === 0 ? ( - Off - ) : ( - On - )} - - )} - {key.includes('Font') && ( - - - {defaultTheme[key as keyof Theme] || - 'Default (Jost)'} - - → - {designerTheme[key as keyof Theme]} + + { + navigator.clipboard.writeText( + defaultTheme[key as keyof Theme] as string, + ); + notifications.show({ + title: ( + + Copied{' '} + { + ThemeProperties[ + key as keyof typeof ThemeProperties + ] + } + + ), + message: ( + + { + designerTheme[ + key as keyof Theme + ] as string + } + + ), + autoClose: true, + withCloseButton: true, + icon: , + }); + }} + color={ + designerTheme[key as keyof Theme] as string + } + style={{ + cursor: 'pointer', + }} + styles={{ + alphaOverlay: { + borderRadius: '0px', + }, + colorOverlay: { + borderRadius: '0px', + }, + shadowOverlay: { + borderRadius: '0px', + }, + childrenOverlay: { + borderRadius: '0px', + }, + }} + /> + )} @@ -657,9 +978,9 @@ export function ThemeEditor({ )} - + )} - +