From ecf061da1fb33346886d5b6d5371a53ed12dcdbf Mon Sep 17 00:00:00 2001 From: Sean Edmunds Date: Tue, 20 Oct 2026 14:16:20 -0500 Subject: [PATCH] Refactor settings management and add mutation error handling --- src/App.tsx | 60 ++--- src/components/WeatherModal/WeatherModal.tsx | 4 +- src/hooks/useAPI.tsx | 68 ++++-- src/hooks/useCommonHooks.ts | 216 ++++++------------ src/pages/homepage/Homepage.tsx | 38 ++- .../components/Applications/Applications.tsx | 8 +- .../components/Bookmarks/Bookmarks.tsx | 9 +- .../homepage/components/Header/Header.tsx | 23 +- .../components/Header/LargeHeader.tsx | 23 +- .../homepage/components/Search/Search.tsx | 54 +++-- .../Search/components/RenderItem.tsx | 4 +- .../Search/components/SearchSelectItem.tsx | 2 + .../SettingsButton/SettingsButton.tsx | 45 +--- .../SettingsButton/SettingsCard.tsx | 54 +++-- .../components/SettingsButton/ThemingCard.tsx | 41 ++-- .../components/Applications/Applications.tsx | 4 +- .../Applications/DebouncedApplication.tsx | 8 +- .../components/Bookmarks/Bookmarks.tsx | 8 +- .../Bookmarks/DebouncedBookmarkItem.tsx | 6 +- .../Bookmarks/DebouncedGroupSettingsItem.tsx | 12 +- .../DebouncedGuacamoleClient.tsx | 8 +- .../GuacamoleClients/GuacamoleClients.tsx | 4 +- .../settings/components/Messages/Messages.tsx | 10 +- .../Personalization/Personalization.tsx | 6 +- .../Search/DebouncedSearchProvider.tsx | 6 +- .../components/Search/SearchProviders.tsx | 4 +- .../components/DeleteBackground.tsx | 2 + .../Backgrounds/components/EditBackground.tsx | 4 + .../Theming/ThemePlaylists/ThemePlaylists.tsx | 16 +- .../components/ThemePlaylistCard.tsx | 6 +- .../components/ThemePlaylistStack.tsx | 9 +- .../Theming/Themes/ThemeCard/ThemeCard.tsx | 11 +- .../components/ThemeManagementPill.tsx | 15 +- .../Theming/Themes/ThemeModal/ThemeModal.tsx | 6 +- .../ThemeModal/components/ThemeChanges.tsx | 22 +- .../ThemeModal/components/ThemeEditor.tsx | 4 +- .../components/ThemeModalContent.tsx | 6 +- .../ThemeModal/components/ThemeOptions.tsx | 8 +- .../components/Theming/Themes/Themes.tsx | 43 ++-- .../components/WoL/DebouncedWolClient.tsx | 6 +- .../settings/components/WoL/WolClients.tsx | 4 +- src/types/index.ts | 1 + src/types/settings.ts | 28 +++ 43 files changed, 476 insertions(+), 440 deletions(-) create mode 100644 src/types/settings.ts diff --git a/src/App.tsx b/src/App.tsx index a57bbd9..dd29c83 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -37,17 +37,11 @@ function App() { const { data: themePlaylists, isFetched: isThemePlaylistsFetched } = useQueryAPI({ endpoint: 'api/themePlaylists', }); - const { data: personalData, isFetched: isPersonalDataFetched } = useQueryAPI({ + const { data: personalData } = useQueryAPI({ endpoint: 'api/personalData', }); - const { - theme, - setTheme, - themeName, - setThemeName, - handleThemeChange, - currentThemePlaylist, - } = useCommonHooks(); + const { settings, updateSetting, theme, setTheme, handleThemeChange } = + useCommonHooks(); const [loaded, setLoaded] = useState(false); const overrides = createTheme({ primaryColor: 'primary', @@ -68,22 +62,23 @@ function App() { 'shift + t', () => { const themeList = JSON.parse( - themePlaylists?.find((t: ThemePlaylist) => t?.name === currentThemePlaylist) - ?.themeList ?? '[]', + themePlaylists?.find( + (t: ThemePlaylist) => t?.name === settings.currentThemePlaylist, + )?.themeList ?? '[]', ); - if (themeList.length > 0 && currentThemePlaylist !== 'Time of Day') { + if (themeList.length > 0 && settings.currentThemePlaylist !== 'Time of Day') { const filteredThemes = allThemes.filter((t: Theme) => themeList.includes(t.id)); handleThemeChange(filteredThemes, false); - } else if (currentThemePlaylist === 'All') { + } else if (settings.currentThemePlaylist === 'All') { handleThemeChange(allThemes, true); - } else if (currentThemePlaylist === 'Backgrounds') { + } else if (settings.currentThemePlaylist === 'Backgrounds') { handleThemeChange( allThemes.filter( (a: any) => !a.backgroundImage.toLowerCase().includes('none'), ), false, ); - } else if (currentThemePlaylist === 'No Backgrounds') { + } else if (settings.currentThemePlaylist === 'No Backgrounds') { handleThemeChange( allThemes.filter((a: any) => a.backgroundImage.toLowerCase().includes('none'), @@ -119,22 +114,26 @@ function App() { useEffect(() => { if ( allThemes && - themeName && + settings.theme && personalData && Object.keys(personalData).length > 0 && isThemePlaylistsFetched ) { - if (currentThemePlaylist === 'All') { - if (themeName === 'random') { + Object.keys(personalData[0]).forEach((key: any) => { + updateSetting(key, personalData[0][key]); + }); + if (settings.currentThemePlaylist === 'All') { + if (settings.theme === 'random') { handleThemeChange(allThemes, false); } else { - const temp = allThemes.find((t: Theme) => t.name === themeName); + const temp = allThemes.find((t: Theme) => t.name === settings.theme); setTheme(temp); } - } else if (currentThemePlaylist === 'Time of Day') { + } else if (settings.currentThemePlaylist === 'Time of Day') { const themeList = JSON.parse( - themePlaylists?.find((t: ThemePlaylist) => t.name === currentThemePlaylist) - .themeList, + themePlaylists?.find( + (t: ThemePlaylist) => t.name === settings.currentThemePlaylist, + ).themeList, ); setTheme( allThemes.find( @@ -142,34 +141,35 @@ function App() { t.id === Number(themeList[Math.floor(new Date().getHours() / 6)]), ), ); - } else if (currentThemePlaylist === 'Backgrounds') { + } else if (settings.currentThemePlaylist === 'Backgrounds') { handleThemeChange( allThemes.filter((a: any) => !a.backgroundImage.toLowerCase().includes('none')), false, ); - } else if (currentThemePlaylist === 'No Backgrounds') { + } else if (settings.currentThemePlaylist === 'No Backgrounds') { handleThemeChange( allThemes.filter((a: any) => a.backgroundImage.toLowerCase().includes('none')), false, ); } else { const themeList = JSON.parse( - themePlaylists?.find((t: ThemePlaylist) => t.name === currentThemePlaylist) - .themeList, + themePlaylists?.find( + (t: ThemePlaylist) => t.name === settings.currentThemePlaylist, + ).themeList, ); const filteredThemes = allThemes.filter((t: Theme) => themeList.includes(t.id)); - setThemeName('random'); + updateSetting('theme', 'random'); handleThemeChange(filteredThemes, false); } setLoaded(true); } }, [ isAllThemesFetched, - themeName, + settings.theme, allThemes, - currentThemePlaylist, + settings.currentThemePlaylist, isThemePlaylistsFetched, - isPersonalDataFetched, + personalData, ]); return ( <> diff --git a/src/components/WeatherModal/WeatherModal.tsx b/src/components/WeatherModal/WeatherModal.tsx index 4235afe..b498081 100644 --- a/src/components/WeatherModal/WeatherModal.tsx +++ b/src/components/WeatherModal/WeatherModal.tsx @@ -19,7 +19,7 @@ export function WeatherModal({ handleResetSearch: () => void; closeWeatherModal: () => void; }) { - const { isMobile, currentUser } = useCommonHooks(); + const { isMobile, settings } = useCommonHooks(); const [selectedDay, setSelectedDay] = useState(undefined); const [selectedHourly, setSelectedHourly] = useState(undefined); @@ -79,7 +79,7 @@ export function WeatherModal({ Weather Forecast for{' '} - {currentUser.physicalAddress} + {settings.physicalAddress} diff --git a/src/hooks/useAPI.tsx b/src/hooks/useAPI.tsx index ff7de0a..ddb24d8 100644 --- a/src/hooks/useAPI.tsx +++ b/src/hooks/useAPI.tsx @@ -306,23 +306,53 @@ export function useMutationAPI() { body: object | undefined | null; }) => callEndpoint(method, endpoint, body), onSuccess: (_, { endpoint }) => { - queryClient.refetchQueries({ - queryKey: ['GET', endpoint], - }); + queryClient + .refetchQueries({ + queryKey: ['GET', endpoint], + }) + .catch((error) => { + console.error(error); + }); endpoint === 'api/bookmarkOrder' && - queryClient.refetchQueries({ queryKey: ['GET', 'api/bookmarks'] }); + queryClient + .refetchQueries({ queryKey: ['GET', 'api/bookmarks'] }) + .catch((error) => { + console.error(error); + }); endpoint === 'api/bookmarkCategoryOrder' && - queryClient.refetchQueries({ queryKey: ['GET', 'api/bookmarkCategories'] }); + queryClient + .refetchQueries({ queryKey: ['GET', 'api/bookmarkCategories'] }) + .catch((error) => { + console.error(error); + }); endpoint === 'api/applicationOrder' && - queryClient.refetchQueries({ queryKey: ['GET', 'api/applications'] }); + queryClient + .refetchQueries({ queryKey: ['GET', 'api/applications'] }) + .catch((error) => { + console.error(error); + }); endpoint === 'api/applications' && - queryClient.refetchQueries({ queryKey: ['GET', 'api/enabledApplications'] }); + queryClient + .refetchQueries({ queryKey: ['GET', 'api/enabledApplications'] }) + .catch((error) => { + console.error(error); + }); endpoint === 'api/bookmarks' && - queryClient.refetchQueries({ queryKey: ['GET', 'api/themes'] }); + queryClient.refetchQueries({ queryKey: ['GET', 'api/themes'] }).catch((error) => { + console.error(error); + }); endpoint === 'api/providers' && - queryClient.refetchQueries({ queryKey: ['GET', 'api/providers/default'] }); + queryClient + .refetchQueries({ queryKey: ['GET', 'api/providers/default'] }) + .catch((error) => { + console.error(error); + }); endpoint === 'api/personalData' && - queryClient.refetchQueries({ queryKey: ['GET', 'api/personalData'] }); + queryClient + .refetchQueries({ queryKey: ['GET', 'api/personalData'] }) + .catch((error) => { + console.error(error); + }); }, }); } @@ -426,9 +456,21 @@ export function useFileUploadAPI() { }) => callEndpoint(method, endpoint, body), onMutate: () => {}, onSuccess: (_variables) => { - queryClient.invalidateQueries({ queryKey: ['GET', 'api/backgrounds'] }); - queryClient.invalidateQueries({ queryKey: ['GET', 'api/themes'] }); - queryClient.invalidateQueries({ queryKey: ['GET', 'api/themePlaylists'] }); + queryClient + .invalidateQueries({ queryKey: ['GET', 'api/backgrounds'] }) + .catch((error) => { + console.error(error); + }); + queryClient + .invalidateQueries({ queryKey: ['GET', 'api/themes'] }) + .catch((error) => { + console.error(error); + }); + queryClient + .invalidateQueries({ queryKey: ['GET', 'api/themePlaylists'] }) + .catch((error) => { + console.error(error); + }); }, }); } diff --git a/src/hooks/useCommonHooks.ts b/src/hooks/useCommonHooks.ts index 6ca9529..50a8af6 100644 --- a/src/hooks/useCommonHooks.ts +++ b/src/hooks/useCommonHooks.ts @@ -2,126 +2,73 @@ import { useLocalStorage } from '@mantine/hooks'; import { appTheme } from 'contexts'; import { useAtom } from 'jotai'; import { useEffect, useState } from 'react'; -import type { Location, Theme, User } from 'types'; +import type { Settings, Theme } from 'types'; import { useMutationAPI } from './useAPI'; +const initialSettings: Settings = { + theme: 'random', + appFilter: ['All'], + appSort: 'A>Z', + appDensity: 6, + appScale: 1, + bookmarkSort: 'A>Z', + bookmarkFilter: ['All'], + bookmarkDensity: 6, + bookmarkScale: 1, + currentThemePlaylist: 'All', + defaultProviderLabel: 'Google Search', + defaultProviderURL: 'https://www.google.com/search?q=', + defaultProviderPrefix: '/g', + defaultProviderIcon: 'FaGoogle', + timeFormat: '12h', + firstName: 'First', + lastName: 'Last', + nickname: 'Boss', + email: 'triggerUser@default.com', + physicalAddress: '1510 Polk St, Houston, TX 77002', + defaultFont: 'Jost', + enableWol: 0, + enableGuacamole: 0, + guacamoleHost: 'https://domain.example.com/guacamole', + lat: 29.750950134386066, + lon: -95.36220654860034, +}; + export function useCommonHooks() { const { mutateAsync } = useMutationAPI(); const isMobile = globalThis.matchMedia('(max-width: 600px)').matches; const [theme, setTheme] = useAtom(appTheme); - const [themeName, setThemeName] = useLocalStorage({ - key: 'theme', - defaultValue: 'random', - }); - const [appFilter, setAppFilter] = useLocalStorage({ - key: 'appFilter', - defaultValue: ['All'], - }); - const [appSort, setAppSort] = useLocalStorage({ - key: 'appSort', - defaultValue: 'A>Z', - }); - const [appDensity, setAppDensity] = useLocalStorage({ - key: 'appDensity', - defaultValue: 6, - }); - const [appScale, setAppScale] = useLocalStorage({ - key: 'appScale', - defaultValue: 1, - }); - const [bookmarkSort, setBookmarkSort] = useLocalStorage({ - key: 'bookmarkSort', - defaultValue: 'A>Z', - }); - const [bookmarkFilter, setBookmarkFilter] = useLocalStorage({ - key: 'bookmarkFilter', - defaultValue: ['All'], - }); - const [bookmarkDensity, setBookmarkDensity] = useLocalStorage({ - key: 'bookmarkDensity', - defaultValue: 6, - }); - const [bookmarkScale, setBookmarkScale] = useLocalStorage({ - key: 'bookmarkScale', - defaultValue: 1, - }); - const [currentTheme, setCurrentTheme] = useLocalStorage({ - key: 'theme', - defaultValue: 'random', - }); - const [currentThemePlaylist, setCurrentThemePlaylist] = useLocalStorage({ - key: 'themePlaylist', - defaultValue: 'All', - }); - const [defaultProviderLabel, setDefaultProviderLabel] = useLocalStorage({ - key: 'providerLabel', - defaultValue: 'Google Search', - }); - const [defaultProviderURL, setDefaultProviderURL] = useLocalStorage({ - key: 'providerURL', - defaultValue: 'https://www.google.com/search?q=', - }); - const [defaultProviderPrefix, setDefaultProviderPrefix] = useLocalStorage({ - key: 'providerPrefix', - defaultValue: '/g', - }); - const [defaultProviderIcon, setDefaultProviderIcon] = useLocalStorage({ - key: 'providerIcon', - defaultValue: 'FaGoogle', - }); - const [timeFormat, setTimeFormat] = useLocalStorage({ - key: 'timeFormat', - defaultValue: '12h', + + const [settings, setSettings] = useLocalStorage({ + key: 'trigger_settings', + defaultValue: initialSettings, }); + + // Helper to update specific keys without wiping the rest of the object + const updateSetting = (key: K, value: Settings[K]) => { + setSettings((prev) => ({ ...prev, [key]: value })); + }; + const [searchValue, setSearchValue] = useState(''); - const [providerLabel, setProviderLabel] = useState(defaultProviderLabel); - const [providerURL, setProviderURL] = useState(defaultProviderURL); - const [providerPrefix, setProviderPrefix] = useState(defaultProviderPrefix); - const [providerIcon, setProviderIcon] = useState(defaultProviderIcon); + const [providerLabel, setProviderLabel] = useState(settings.defaultProviderLabel); + const [providerURL, setProviderURL] = useState(settings.defaultProviderURL); + const [providerPrefix, setProviderPrefix] = useState(settings.defaultProviderPrefix); + const [providerIcon, setProviderIcon] = useState(settings.defaultProviderIcon); useEffect(() => { - setProviderLabel(defaultProviderLabel); - setProviderURL(defaultProviderURL); - setProviderPrefix(defaultProviderPrefix); - setProviderIcon(defaultProviderIcon); + setProviderLabel(settings.defaultProviderLabel); + setProviderURL(settings.defaultProviderURL); + setProviderPrefix(settings.defaultProviderPrefix); + setProviderIcon(settings.defaultProviderIcon); }, [ - defaultProviderLabel, - defaultProviderURL, - defaultProviderPrefix, - defaultProviderIcon, + settings.defaultProviderLabel, + settings.defaultProviderURL, + settings.defaultProviderPrefix, + settings.defaultProviderIcon, ]); - const [currentUser, setCurrentUser] = useLocalStorage({ - key: 'user', - defaultValue: { - firstName: 'First', - lastName: 'Last', - nickname: 'Boss', - email: 'triggerUser@default.com', - physicalAddress: '1510 Polk St, Houston, TX 77002', - defaultFont: 'Jost', - enableWol: 0, - enableGuacamole: 0, - guacamoleHost: 'https://domain.example.com/guacamole', - }, - }); - const [currentLocation, setCurrentLocation] = useLocalStorage({ - key: 'location', - defaultValue: { - lat: 29.750950134386066, - lon: -95.36220654860034, - }, - }); - - const urlPattern = new RegExp( - String.raw`^(https?:\/\/)?` + - String.raw`((([a-z\d]([a-z\d-]*[a-z\d])*)\.)+[a-z]{2,}|` + - String.raw`((\d{1,3}\.){3}\d{1,3}))` + - String.raw`(\:\d+)?(\/[-a-z\d%_.~+]*)*` + - String.raw`(\?[;&a-z\d%_.~+=-]*)?` + - String.raw`(\#[-a-z\d_]*)?$`, - 'i', - ); + const urlPattern = + /^(https?:\/\/)?([\w.-]+)\.([a-z]{2,})(:\d+)?(\/[-a-z\d%_.~+]*)*(\?[;&a-z\d%_.~+=-]*)?(#[-a-z\d_]*)?$/i; const textShadowStyle = '1px 1px 1px color-mix(in srgb, var(--mantine-color-accent-0), transparent 50%)'; @@ -139,22 +86,24 @@ export function useCommonHooks() { const enabled = themes .filter((t: Theme) => t.randomEnabled === 1) .filter((t: Theme) => t.name !== theme.name); - if (enabled.length === 0 && currentThemePlaylist === 'All') { + if (enabled.length === 0 && settings.currentThemePlaylist === 'All') { setTheme(themes[0]); - save && setThemeName(themes[0].name); - } else if (currentThemePlaylist === 'All') { + if (save) updateSetting('theme', themes[0].name); + } else if (settings.currentThemePlaylist === 'All') { const index = Math.floor(Math.random() * enabled.length); setTheme(enabled[index]); - save && setThemeName(enabled[index].name); + if (save) updateSetting('theme', enabled[index].name); } else { const index = Math.floor(Math.random() * themes.length); setTheme(themes[index]); - save && setThemeName(themes[index].name); + if (save) updateSetting('theme', themes[index].name); } }; const handleDelete = (item: any, endpoint: string) => { - mutateAsync({ method: 'DELETE', endpoint: endpoint, body: item }); + mutateAsync({ method: 'DELETE', endpoint: endpoint, body: item }).catch((error) => { + console.error(error); + }); }; const iconFilter = (selectedTheme?: Theme) => { @@ -178,7 +127,6 @@ export function useCommonHooks() { const 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] = { @@ -191,7 +139,6 @@ export function useCommonHooks() { const originalValue = original[key]; const currentValue = value; - // Handle different types of comparisons if ( originalValue !== currentValue && String(originalValue) !== String(currentValue) && @@ -204,7 +151,6 @@ export function useCommonHooks() { } } - // Check for removed properties for (const key of Object.keys(original)) { if (!(key in current)) { changes[key] = { @@ -218,6 +164,8 @@ export function useCommonHooks() { }; return { + settings, + updateSetting, isMobile, theme, setTheme, @@ -228,28 +176,6 @@ export function useCommonHooks() { getObjectDiff, handleThemeChange, handleDelete, - themeName, - setThemeName, - appFilter, - setAppFilter, - appSort, - setAppSort, - appDensity, - setAppDensity, - appScale, - setAppScale, - bookmarkSort, - setBookmarkSort, - bookmarkFilter, - setBookmarkFilter, - bookmarkDensity, - setBookmarkDensity, - bookmarkScale, - setBookmarkScale, - currentTheme, - setCurrentTheme, - currentThemePlaylist, - setCurrentThemePlaylist, searchValue, setSearchValue, providerLabel, @@ -260,20 +186,6 @@ export function useCommonHooks() { setProviderPrefix, providerIcon, setProviderIcon, - defaultProviderLabel, - setDefaultProviderLabel, - defaultProviderURL, - setDefaultProviderURL, - defaultProviderPrefix, - setDefaultProviderPrefix, - defaultProviderIcon, - setDefaultProviderIcon, - timeFormat, - setTimeFormat, - currentUser, - setCurrentUser, - currentLocation, - setCurrentLocation, textShadowStyle, largeTextShadowStyle, }; diff --git a/src/pages/homepage/Homepage.tsx b/src/pages/homepage/Homepage.tsx index 0562992..b496382 100644 --- a/src/pages/homepage/Homepage.tsx +++ b/src/pages/homepage/Homepage.tsx @@ -15,14 +15,7 @@ import { } from './components'; export function Homepage() { - const { - appFilter, - bookmarkFilter, - isMobile, - setCurrentUser, - currentLocation, - setCurrentLocation, - } = useCommonHooks(); + const { isMobile, settings, updateSetting } = useCommonHooks(); const dateOptions: Intl.DateTimeFormatOptions = isMobile ? {} : { @@ -34,7 +27,7 @@ export function Homepage() { const date = new Date().toLocaleDateString('en-US', dateOptions); - const { data: personalData, isFetched: personalIsFetched } = useQueryAPI({ + const { data: personalData } = useQueryAPI({ endpoint: 'api/personalData', }); const { data: messageData } = useQueryAPI({ @@ -44,8 +37,8 @@ export function Homepage() { address: personalData?.[0]?.physicalAddress, }); const { data: meteoWeather } = useOpenMeteoAPI({ - lat: weatherMetadata?.[0].lat ?? currentLocation.lat, - lon: weatherMetadata?.[0].lon ?? currentLocation.lon, + lat: weatherMetadata?.[0].lat ?? settings.lat, + lon: weatherMetadata?.[0].lon ?? settings.lon, }); const personal: PersonalData = personalData?.[0]; @@ -59,11 +52,6 @@ export function Homepage() { const [weatherModalOpened, { open: openWeatherModal, close: closeWeatherModal }] = useDisclosure(false); - useEffect(() => { - if (personalData && personalIsFetched) { - setCurrentUser(personalData[0]); - } - }, [personalData, personalIsFetched]); useEffect(() => { if (personal) { setDisplayedGreeting(() => { @@ -87,21 +75,23 @@ export function Homepage() { useEffect(() => { if (meteoWeather) { setMeteoCurrent(meteoWeather); - setCurrentLocation({ - lat: weatherMetadata?.[0].lat, - lon: weatherMetadata?.[0].lon, - }); + updateSetting('lat', weatherMetadata?.[0].lat); + updateSetting('lon', weatherMetadata?.[0].lon); } }, [meteoWeather]); return ( 0 || bookmarkFilter.length > 0 ? undefined : '100%'} + h={ + settings.appFilter.length > 0 || settings.bookmarkFilter.length > 0 + ? undefined + : '100%' + } className={stackClasses.containerStack} justify='center' > - {appFilter.length > 0 || bookmarkFilter.length > 0 ? ( + {settings.appFilter.length > 0 || settings.bookmarkFilter.length > 0 ? ( <> - - + + ) : ( diff --git a/src/pages/homepage/components/Applications/Applications.tsx b/src/pages/homepage/components/Applications/Applications.tsx index c572193..f497f93 100644 --- a/src/pages/homepage/components/Applications/Applications.tsx +++ b/src/pages/homepage/components/Applications/Applications.tsx @@ -8,10 +8,10 @@ export function Applications({ contentType }: { contentType: string[] }) { const { data: applicationData } = useQueryAPI({ endpoint: 'api/enabledApplications', }); - const { appSort, appDensity, appScale, theme, textShadowStyle } = useCommonHooks(); + const { settings, theme, textShadowStyle } = useCommonHooks(); const applications: Application[] = applicationData ?.sort((a: Application, b: Application) => { - switch (appSort) { + switch (settings.appSort) { case 'A>Z': return a.name.toLocaleLowerCase() > b.name.toLocaleLowerCase() ? 1 : -1; case 'Z>A': @@ -54,7 +54,7 @@ export function Applications({ contentType }: { contentType: string[] }) { style={{ gap: '.25rem', display: 'grid', - gridTemplateColumns: `repeat(${appDensity}, 1fr)`, + gridTemplateColumns: `repeat(${settings.appDensity}, 1fr)`, }} > {applications?.map((application: Application) => { @@ -65,7 +65,7 @@ export function Applications({ contentType }: { contentType: string[] }) { url={application.url} icon={application.icon} enabled={application.enabled} - scale={appScale} + scale={settings.appScale} linksActive /> ); diff --git a/src/pages/homepage/components/Bookmarks/Bookmarks.tsx b/src/pages/homepage/components/Bookmarks/Bookmarks.tsx index 7b70ec0..7b0975d 100644 --- a/src/pages/homepage/components/Bookmarks/Bookmarks.tsx +++ b/src/pages/homepage/components/Bookmarks/Bookmarks.tsx @@ -11,15 +11,14 @@ export function Bookmarks({ contentType }: { contentType: string[] }) { const { data: groupData, isFetched: groupsIsFetched } = useQueryAPI({ endpoint: 'api/bookmarkCategories', }); - const { bookmarkSort, bookmarkDensity, bookmarkScale, theme, textShadowStyle } = - useCommonHooks(); + const { settings, theme, textShadowStyle } = useCommonHooks(); const groupList: BookmarkGroup[] = groupData?.map((category: BookmarkGroup) => { return category; }); const bookmarks: Bookmark[] = bookmarkData || []; const groups: BookmarkGroup[] = groupList ?.toSorted((a: BookmarkGroup, b: BookmarkGroup) => { - switch (bookmarkSort) { + switch (settings.bookmarkSort) { case 'A>Z': return a.categoryName.toLocaleLowerCase() > b.categoryName.toLocaleLowerCase() ? 1 @@ -71,7 +70,7 @@ export function Bookmarks({ contentType }: { contentType: string[] }) { style={{ display: 'grid', gridRowGap: '0px', - gridTemplateColumns: `repeat(${bookmarkDensity}, 1fr)`, + gridTemplateColumns: `repeat(${settings.bookmarkDensity}, 1fr)`, }} > {groups @@ -88,7 +87,7 @@ export function Bookmarks({ contentType }: { contentType: string[] }) { (bookmark: Bookmark) => bookmark.category === category.categoryName, )} - bookmarkScale={bookmarkScale} + bookmarkScale={settings.bookmarkScale} /> ); })} diff --git a/src/pages/homepage/components/Header/Header.tsx b/src/pages/homepage/components/Header/Header.tsx index bac6157..3a07174 100644 --- a/src/pages/homepage/components/Header/Header.tsx +++ b/src/pages/homepage/components/Header/Header.tsx @@ -18,13 +18,12 @@ export function Header({ const [time, setTime] = useState(new Date()); const { isMobile, - currentUser, fixDigits, theme, textShadowStyle, largeTextShadowStyle, - timeFormat, - setTimeFormat, + settings, + updateSetting, } = useCommonHooks(); useEffect(() => { @@ -51,12 +50,12 @@ export function Header({ }} > {greet - ?.replace('$firstName', currentUser.firstName) - .replace('$lastName', currentUser.lastName) - .replace('$nickname', currentUser.nickname) - .replace('$^firstName', currentUser.firstName.toUpperCase()) - .replace('$^lastName', currentUser.lastName.toUpperCase()) - .replace('$^nickname', currentUser.nickname?.toUpperCase())} + ?.replace('$firstName', settings.firstName) + .replace('$lastName', settings.lastName) + .replace('$nickname', settings.nickname) + .replace('$^firstName', settings.firstName.toUpperCase()) + .replace('$^lastName', settings.lastName.toUpperCase()) + .replace('$^nickname', settings.nickname?.toUpperCase())} - timeFormat === '12h' ? setTimeFormat('24h') : setTimeFormat('12h') + settings.timeFormat === '12h' + ? updateSetting('timeFormat', '24h') + : updateSetting('timeFormat', '12h') } > - {timeFormat === '12h' + {settings.timeFormat === '12h' ? `${ time.getHours() === 0 ? 12 diff --git a/src/pages/homepage/components/Header/LargeHeader.tsx b/src/pages/homepage/components/Header/LargeHeader.tsx index 55157bb..d6d2746 100644 --- a/src/pages/homepage/components/Header/LargeHeader.tsx +++ b/src/pages/homepage/components/Header/LargeHeader.tsx @@ -13,13 +13,12 @@ export function LargeHeader({ const [time, setTime] = useState(new Date()); const { isMobile, - currentUser, fixDigits, theme, textShadowStyle, largeTextShadowStyle, - timeFormat, - setTimeFormat, + settings, + updateSetting, } = useCommonHooks(); useEffect(() => { @@ -40,12 +39,12 @@ export function LargeHeader({ }} > {greet - ?.replace('$firstName', currentUser.firstName) - .replace('$lastName', currentUser.lastName) - .replace('$nickname', currentUser.nickname) - .replace('$^firstName', currentUser.firstName.toUpperCase()) - .replace('$^lastName', currentUser.lastName.toUpperCase()) - .replace('$^nickname', currentUser.nickname?.toUpperCase())} + ?.replace('$firstName', settings.firstName) + .replace('$lastName', settings.lastName) + .replace('$nickname', settings.nickname) + .replace('$^firstName', settings.firstName.toUpperCase()) + .replace('$^lastName', settings.lastName.toUpperCase()) + .replace('$^nickname', settings.nickname?.toUpperCase())} - timeFormat === '12h' ? setTimeFormat('24h') : setTimeFormat('12h') + settings.timeFormat === '12h' + ? updateSetting('timeFormat', '24h') + : updateSetting('timeFormat', '12h') } > - {timeFormat === '12h' + {settings.timeFormat === '12h' ? `${ time.getHours() === 0 ? 12 diff --git a/src/pages/homepage/components/Search/Search.tsx b/src/pages/homepage/components/Search/Search.tsx index b66cc20..ff56738 100644 --- a/src/pages/homepage/components/Search/Search.tsx +++ b/src/pages/homepage/components/Search/Search.tsx @@ -63,14 +63,8 @@ export function Search({ setProviderIcon, searchValue, setSearchValue, - defaultProviderURL, - setDefaultProviderURL, - defaultProviderLabel, - setDefaultProviderLabel, - defaultProviderPrefix, - setDefaultProviderPrefix, - defaultProviderIcon, - setDefaultProviderIcon, + settings, + updateSetting, } = useCommonHooks(); const { ref, height } = useElementSize(); const { mutateAsync } = useMutationAPI(); @@ -146,8 +140,8 @@ export function Search({ setSearchValue(''); setListIndex(-1); setHistoryMultiplier(1); - setProviderLabel(defaultProviderLabel); - setProviderURL(defaultProviderURL); + setProviderLabel(settings.defaultProviderLabel); + setProviderURL(settings.defaultProviderURL); }; const handleGuacamoleClientLaunchItem = ({ option }: { option: any }) => { @@ -176,9 +170,13 @@ export function Search({ method: 'POST', endpoint: searchEndpoint, body: { prefix: providerPrefix, provider: providerLabel, searchTerm: subtext }, - }).then(() => { - open(`${providerURL}${subtext}`, '_self'); - }); + }) + .then(() => { + open(`${providerURL}${subtext}`, '_self'); + }) + .catch((error) => { + console.error(error); + }); } else if (providerLabel === 'Show weather') { setSearchValue(''); closeDropdown(); @@ -211,9 +209,13 @@ export function Search({ method: 'POST', endpoint: searchEndpoint, body: { prefix: providerPrefix, provider: providerLabel, searchTerm: subtext }, - }).then(() => { - open(`${providerURL}${subtext}`, '_self'); - }); + }) + .then(() => { + open(`${providerURL}${subtext}`, '_self'); + }) + .catch((error) => { + console.error(error); + }); } else { open(`${providerURL}${subtext}`, '_self'); } @@ -372,10 +374,10 @@ export function Search({ setProviderIcon(''); } } else { - setProviderLabel(defaultProviderLabel); - setProviderURL(defaultProviderURL); - setProviderPrefix(defaultProviderPrefix); - setProviderIcon(defaultProviderIcon); + setProviderLabel(settings.defaultProviderLabel); + setProviderURL(settings.defaultProviderURL); + setProviderPrefix(settings.defaultProviderPrefix); + setProviderIcon(settings.defaultProviderIcon); } }; @@ -460,12 +462,16 @@ export function Search({ useEffect(() => { if (defaultProviderData && defaultProviderDataIsFetched) { - setDefaultProviderURL( + updateSetting( + 'defaultProviderURL', defaultProviderData[0]?.url ?? 'https://www.google.com/search?q=', ); - setDefaultProviderPrefix(defaultProviderData[0]?.prefix ?? '/g'); - setDefaultProviderLabel(defaultProviderData[0]?.name ?? 'Google Search'); - setDefaultProviderIcon(defaultProviderData[0]?.icon ?? 'FaGoogle'); + updateSetting('defaultProviderPrefix', defaultProviderData[0]?.prefix ?? '/g'); + updateSetting('defaultProviderIcon', defaultProviderData[0]?.icon ?? 'FaGoogle'); + updateSetting( + 'defaultProviderLabel', + defaultProviderData[0]?.name ?? 'Google Search', + ); } }, [defaultProviderData, defaultProviderDataIsFetched]); diff --git a/src/pages/homepage/components/Search/components/RenderItem.tsx b/src/pages/homepage/components/Search/components/RenderItem.tsx index 4d27b2d..2da67db 100644 --- a/src/pages/homepage/components/Search/components/RenderItem.tsx +++ b/src/pages/homepage/components/Search/components/RenderItem.tsx @@ -24,11 +24,11 @@ export default function RenderItem({ setHistoryMultiplier: React.Dispatch>; searchEndpoint: string; }) { - const { defaultProviderURL } = useCommonHooks(); + const { settings } = useCommonHooks(); const handleSearchHistoryItem = ({ option }: { option: SearchHistoryItem }) => { const url = providers.find((provider: Provider) => provider.prefix === option.prefix)?.url ?? - defaultProviderURL; + settings.defaultProviderURL; open(`${url}${option.searchTerm}`, '_self'); }; diff --git a/src/pages/homepage/components/Search/components/SearchSelectItem.tsx b/src/pages/homepage/components/Search/components/SearchSelectItem.tsx index 7087c11..b0ec4b8 100644 --- a/src/pages/homepage/components/Search/components/SearchSelectItem.tsx +++ b/src/pages/homepage/components/Search/components/SearchSelectItem.tsx @@ -130,6 +130,8 @@ function SearchSelectItem({ method: 'DELETE', endpoint: searchEndpoint, body: { id: item.option.id }, + }).catch((error) => { + console.error(error); }); }} > diff --git a/src/pages/homepage/components/SettingsButton/SettingsButton.tsx b/src/pages/homepage/components/SettingsButton/SettingsButton.tsx index 9192045..4da5973 100644 --- a/src/pages/homepage/components/SettingsButton/SettingsButton.tsx +++ b/src/pages/homepage/components/SettingsButton/SettingsButton.tsx @@ -33,26 +33,7 @@ export function SettingsButton({ openProviderModal }: { openProviderModal: () => const [selectedClient, setSelectedClient] = useState(wolClientData?.[0]); const navigate = useNavigate(); const [isOpen, setIsOpen] = useState(false); - const { - theme, - isMobile, - appFilter, - setAppFilter, - appSort, - setAppSort, - appDensity, - setAppDensity, - appScale, - setAppScale, - bookmarkSort, - setBookmarkSort, - bookmarkFilter, - setBookmarkFilter, - bookmarkDensity, - setBookmarkDensity, - bookmarkScale, - setBookmarkScale, - } = useCommonHooks(); + const { theme, isMobile, settings } = useCommonHooks(); const handleWakeRequest = () => { mutateAsync({ @@ -123,26 +104,18 @@ export function SettingsButton({ openProviderModal }: { openProviderModal: () => diff --git a/src/pages/homepage/components/SettingsButton/SettingsCard.tsx b/src/pages/homepage/components/SettingsButton/SettingsCard.tsx index f1d1a8f..0edb5ac 100644 --- a/src/pages/homepage/components/SettingsButton/SettingsCard.tsx +++ b/src/pages/homepage/components/SettingsButton/SettingsCard.tsx @@ -14,26 +14,18 @@ function SettingsCard({ categories, sectionTitle, filter, - setFilter, sort, - setSort, density, - setDensity, scale, - setScale, }: { categories: ComboboxItem[]; sectionTitle: string; filter: any; - setFilter: any; sort: any; - setSort: any; density: any; - setDensity: any; scale: any; - setScale: any; }) { - const { theme } = useCommonHooks(); + const { theme, updateSetting } = useCommonHooks(); return ( setDensity(value)} + onChange={(value) => { + if (sectionTitle === 'Applications') { + updateSetting('appDensity', value); + } else if (sectionTitle === 'Bookmarks') { + updateSetting('bookmarkDensity', value); + } + }} min={1} max={16} marks={[{ value: 6, label: 'Default' }]} - onDoubleClick={() => setDensity(6)} + onDoubleClick={() => { + if (sectionTitle === 'Applications') { + updateSetting('appDensity', 6); + } else if (sectionTitle === 'Bookmarks') { + updateSetting('bookmarkDensity', 6); + } + }} /> {scale !== undefined && ( @@ -86,12 +90,24 @@ function SettingsCard({ className={sliderClasses.default} classNames={sliderClasses} value={scale} - onChange={(value) => setScale(value)} + onChange={(value) => { + if (sectionTitle === 'Applications') { + updateSetting('appScale', value); + } else if (sectionTitle === 'Bookmarks') { + updateSetting('bookmarkScale', value); + } + }} step={0.1} min={0.2} max={3} marks={[{ value: 1, label: 'Default' }]} - onDoubleClick={() => setScale(1)} + onDoubleClick={() => { + if (sectionTitle === 'Applications') { + updateSetting('appScale', 1); + } else if (sectionTitle === 'Bookmarks') { + updateSetting('bookmarkScale', 1); + } + }} /> )} @@ -113,7 +129,11 @@ function SettingsCard({ } defaultValue={filter} onChange={(data: string[]) => { - setFilter(data); + if (sectionTitle === 'Applications') { + updateSetting('appFilter', data); + } else if (sectionTitle === 'Bookmarks') { + updateSetting('bookmarkFilter', data); + } }} classNames={multiSelectClasses} comboboxProps={{ @@ -147,7 +167,11 @@ function SettingsCard({ position: 'top', }} onChange={(_value, option: ComboboxItem) => { - setSort(option.value); + if (sectionTitle === 'Applications') { + updateSetting('appSort', option.value); + } else if (sectionTitle === 'Bookmarks') { + updateSetting('bookmarkSort', option.value); + } }} labelProps={{ top: 8 }} styles={ diff --git a/src/pages/homepage/components/SettingsButton/ThemingCard.tsx b/src/pages/homepage/components/SettingsButton/ThemingCard.tsx index deccbcb..9e997b8 100644 --- a/src/pages/homepage/components/SettingsButton/ThemingCard.tsx +++ b/src/pages/homepage/components/SettingsButton/ThemingCard.tsx @@ -31,16 +31,8 @@ function ThemingCard({ wolEnabled }: { wolEnabled: number }) { }); const allThemes: Theme[] = allThemeData || []; - const { - isMobile, - currentTheme, - setCurrentTheme, - setThemeName, - handleThemeChange, - theme, - currentThemePlaylist, - setCurrentThemePlaylist, - } = useCommonHooks(); + const { isMobile, handleThemeChange, theme, settings, updateSetting } = + useCommonHooks(); const [current, setCurrent] = useState(theme.name); @@ -128,11 +120,11 @@ function ThemingCard({ wolEnabled }: { wolEnabled: number }) { borderRadius: '50%', }, }} - disabled={currentThemePlaylist === 'Time of Day' || isAnimating} + disabled={settings.currentThemePlaylist === 'Time of Day' || isAnimating} onClick={() => { const themeList = JSON.parse( themePlaylistData?.find( - (t: ThemePlaylist) => t?.name === currentThemePlaylist, + (t: ThemePlaylist) => t?.name === settings.currentThemePlaylist, )?.themeList ?? '[]', ); if (themeList.length > 0) { @@ -140,16 +132,16 @@ function ThemingCard({ wolEnabled }: { wolEnabled: number }) { themeList.includes(t.id), ); handleThemeChange(filteredThemes, false); - } else if (currentThemePlaylist === 'All') { + } else if (settings.currentThemePlaylist === 'All') { handleThemeChange(allThemes, true); - } else if (currentThemePlaylist === 'Backgrounds') { + } else if (settings.currentThemePlaylist === 'Backgrounds') { handleThemeChange( allThemes.filter( (a: any) => !a.backgroundImage.toLowerCase().includes('none'), ), false, ); - } else if (currentThemePlaylist === 'No Backgrounds') { + } else if (settings.currentThemePlaylist === 'No Backgrounds') { handleThemeChange( allThemes.filter((a: any) => a.backgroundImage.toLowerCase().includes('none'), @@ -169,7 +161,7 @@ function ThemingCard({ wolEnabled }: { wolEnabled: number }) { placeholder='Pick a playlist...' mb={'.25rem'} ml={'.25rem'} - value={currentThemePlaylist} + value={settings.currentThemePlaylist} data={[ { value: 'All', label: 'All' }, { @@ -226,20 +218,21 @@ function ThemingCard({ wolEnabled }: { wolEnabled: number }) { : undefined } onChange={(_value, option: ComboboxItem) => { - setCurrentThemePlaylist(option.value); + updateSetting('currentThemePlaylist', option.value); if (option.value === 'Time of Day') { const themeList = JSON.parse( themePlaylistData.find((t: ThemePlaylist) => t.name === 'Time of Day') .themeList, ); - setThemeName( + updateSetting( + 'theme', allThemeData.find( (t: Theme) => t.id === Number(themeList[Math.floor(new Date().getHours() / 6)]), ).name, ); } else { - setThemeName('random'); + updateSetting('theme', 'random'); } }} /> @@ -252,12 +245,12 @@ function ThemingCard({ wolEnabled }: { wolEnabled: number }) { { - setCurrentTheme(currentTheme === 'random' ? theme.name : 'random'); - setCurrentThemePlaylist('All'); + updateSetting('theme', 'random'); + updateSetting('currentThemePlaylist', 'All'); }} > diff --git a/src/pages/settings/components/Applications/Applications.tsx b/src/pages/settings/components/Applications/Applications.tsx index e2efa4b..06841e5 100644 --- a/src/pages/settings/components/Applications/Applications.tsx +++ b/src/pages/settings/components/Applications/Applications.tsx @@ -128,10 +128,12 @@ export function Applications() { useEffect(() => { if (applicationList.length > 0 && applicationList !== applications) { - void mutateAsync({ + mutateAsync({ method: 'PATCH', endpoint: appsOrderEndpoint, body: applicationList, + }).catch((error) => { + console.error(error); }); } }, [applicationList]); diff --git a/src/pages/settings/components/Applications/DebouncedApplication.tsx b/src/pages/settings/components/Applications/DebouncedApplication.tsx index 589983d..dc7d322 100644 --- a/src/pages/settings/components/Applications/DebouncedApplication.tsx +++ b/src/pages/settings/components/Applications/DebouncedApplication.tsx @@ -38,7 +38,13 @@ function DebouncedApplication({ }; useEffect(() => { if (debounced && Object.keys(debounced).length > 0) { - mutateAsync({ method: 'PATCH', endpoint: 'api/applications', body: debounced }); + mutateAsync({ + method: 'PATCH', + endpoint: 'api/applications', + body: debounced, + }).catch((error) => { + console.error(error); + }); } }, [debounced]); diff --git a/src/pages/settings/components/Bookmarks/Bookmarks.tsx b/src/pages/settings/components/Bookmarks/Bookmarks.tsx index 87e7b3b..49c1b3c 100644 --- a/src/pages/settings/components/Bookmarks/Bookmarks.tsx +++ b/src/pages/settings/components/Bookmarks/Bookmarks.tsx @@ -142,10 +142,12 @@ export function Bookmarks() { useEffect(() => { if (groupList.length > 0 && groupList !== groups) { - void mutateAsync({ + mutateAsync({ method: 'PATCH', endpoint: 'api/bookmarkCategoryOrder', body: groupList, + }).catch((error) => { + console.error(error); }); } }, [groupList]); @@ -160,13 +162,15 @@ export function Bookmarks() { body={
{ - void mutateAsync({ + mutateAsync({ method: 'POST', endpoint: categoriesEndpoint, body: { ...values, categoryIndex: groups.length, }, + }).catch((error) => { + console.error(error); }); handleClose(); })} diff --git a/src/pages/settings/components/Bookmarks/DebouncedBookmarkItem.tsx b/src/pages/settings/components/Bookmarks/DebouncedBookmarkItem.tsx index 9ff98cd..a411b5b 100644 --- a/src/pages/settings/components/Bookmarks/DebouncedBookmarkItem.tsx +++ b/src/pages/settings/components/Bookmarks/DebouncedBookmarkItem.tsx @@ -33,7 +33,11 @@ function DebouncedBookmarkItem({ }; useEffect(() => { if (debounced && Object.keys(debounced).length) { - mutateAsync({ method: 'PATCH', endpoint: 'api/bookmarks', body: debounced }); + mutateAsync({ method: 'PATCH', endpoint: 'api/bookmarks', body: debounced }).catch( + (error) => { + console.error(error); + }, + ); } }, [debounced]); diff --git a/src/pages/settings/components/Bookmarks/DebouncedGroupSettingsItem.tsx b/src/pages/settings/components/Bookmarks/DebouncedGroupSettingsItem.tsx index c2fa95f..3b7dd6d 100644 --- a/src/pages/settings/components/Bookmarks/DebouncedGroupSettingsItem.tsx +++ b/src/pages/settings/components/Bookmarks/DebouncedGroupSettingsItem.tsx @@ -94,6 +94,8 @@ function DebouncedGroupSettingsItem({ method: 'PATCH', endpoint: 'api/bookmarkCategories', body: debounced, + }).catch((error) => { + console.error(error); }); setUpdate(undefined); } @@ -107,7 +109,13 @@ function DebouncedGroupSettingsItem({ useEffect(() => { if (bookmarkList && bookmarkList !== bookmarks) { - mutateAsync({ method: 'PATCH', endpoint: 'api/bookmarkOrder', body: bookmarkList }); + mutateAsync({ + method: 'PATCH', + endpoint: 'api/bookmarkOrder', + body: bookmarkList, + }).catch((error) => { + console.error(error); + }); } }, [bookmarkList]); @@ -351,6 +359,8 @@ function DebouncedGroupSettingsItem({ method: 'POST', endpoint: 'api/bookmarks', body: { ...values, index: bookmarks.length }, + }).catch((error) => { + console.error(error); }); setPopoverOpened(false); form.reset(); diff --git a/src/pages/settings/components/GuacamoleClients/DebouncedGuacamoleClient.tsx b/src/pages/settings/components/GuacamoleClients/DebouncedGuacamoleClient.tsx index 1ba08df..5c2994c 100644 --- a/src/pages/settings/components/GuacamoleClients/DebouncedGuacamoleClient.tsx +++ b/src/pages/settings/components/GuacamoleClients/DebouncedGuacamoleClient.tsx @@ -47,7 +47,13 @@ function DebouncedGuacamoleClient({ useEffect(() => { if (debounced && Object.keys(debounced).length) { - mutateAsync({ method: 'PATCH', endpoint: 'api/guacamoleClients', body: debounced }); + mutateAsync({ + method: 'PATCH', + endpoint: 'api/guacamoleClients', + body: debounced, + }).catch((error) => { + console.error(error); + }); } }, [debounced]); diff --git a/src/pages/settings/components/GuacamoleClients/GuacamoleClients.tsx b/src/pages/settings/components/GuacamoleClients/GuacamoleClients.tsx index 9221b3b..03d8283 100644 --- a/src/pages/settings/components/GuacamoleClients/GuacamoleClients.tsx +++ b/src/pages/settings/components/GuacamoleClients/GuacamoleClients.tsx @@ -108,10 +108,12 @@ export function GuacamoleClients() { body={ { - void mutateAsync({ + mutateAsync({ method: 'POST', endpoint: endpoint, body: { ...values, enabled: 1 }, + }).catch((error) => { + console.error(error); }); handleClose(); })} diff --git a/src/pages/settings/components/Messages/Messages.tsx b/src/pages/settings/components/Messages/Messages.tsx index edd5c4e..a27d455 100644 --- a/src/pages/settings/components/Messages/Messages.tsx +++ b/src/pages/settings/components/Messages/Messages.tsx @@ -71,7 +71,11 @@ export function Messages() { useEffect(() => { if (Object.keys(debounced).length) { - void mutateAsync({ method: 'PATCH', endpoint: endpoint, body: debounced }); + mutateAsync({ method: 'PATCH', endpoint: endpoint, body: debounced }).catch( + (error) => { + console.error(error); + }, + ); } }, [debounced]); @@ -116,10 +120,12 @@ export function Messages() { body={ { - void mutateAsync({ + mutateAsync({ method: 'POST', endpoint: endpoint, body: { message: values.message }, + }).catch((error) => { + console.error(error); }); handleClose(); })} diff --git a/src/pages/settings/components/Personalization/Personalization.tsx b/src/pages/settings/components/Personalization/Personalization.tsx index 974f3f6..4ace0c3 100644 --- a/src/pages/settings/components/Personalization/Personalization.tsx +++ b/src/pages/settings/components/Personalization/Personalization.tsx @@ -37,7 +37,11 @@ export function Personalization() { const { isMobile, theme } = useCommonHooks(); useEffect(() => { if (debounced && Object.keys(debounced).length) { - void mutateAsync({ method: 'PATCH', endpoint: endpoint, body: debounced }); + mutateAsync({ method: 'PATCH', endpoint: endpoint, body: debounced }).catch( + (error) => { + console.error(error); + }, + ); setUpdate(undefined); } }, [debounced]); diff --git a/src/pages/settings/components/Search/DebouncedSearchProvider.tsx b/src/pages/settings/components/Search/DebouncedSearchProvider.tsx index b17c8e8..303ad4f 100644 --- a/src/pages/settings/components/Search/DebouncedSearchProvider.tsx +++ b/src/pages/settings/components/Search/DebouncedSearchProvider.tsx @@ -40,7 +40,11 @@ function DebouncedSearchProvider({ useEffect(() => { if (debounced && Object.keys(debounced).length) { - mutateAsync({ method: 'PATCH', endpoint: 'api/providers', body: debounced }); + mutateAsync({ method: 'PATCH', endpoint: 'api/providers', body: debounced }).catch( + (error) => { + console.error(error); + }, + ); } }, [debounced]); diff --git a/src/pages/settings/components/Search/SearchProviders.tsx b/src/pages/settings/components/Search/SearchProviders.tsx index 88cf95a..94332a5 100644 --- a/src/pages/settings/components/Search/SearchProviders.tsx +++ b/src/pages/settings/components/Search/SearchProviders.tsx @@ -116,10 +116,12 @@ export function SearchProviders() { body={ { - void mutateAsync({ + mutateAsync({ method: 'POST', endpoint: endpoint, body: values, + }).catch((error) => { + console.error(error); }); handleClose(); })} diff --git a/src/pages/settings/components/Theming/Backgrounds/components/DeleteBackground.tsx b/src/pages/settings/components/Theming/Backgrounds/components/DeleteBackground.tsx index 059e8f2..3e8f124 100644 --- a/src/pages/settings/components/Theming/Backgrounds/components/DeleteBackground.tsx +++ b/src/pages/settings/components/Theming/Backgrounds/components/DeleteBackground.tsx @@ -59,6 +59,8 @@ export function DeleteBackground({ method: 'DELETE', endpoint: 'api/backgrounds', body: { fileName }, + }).catch((error) => { + console.error(error); }); }} > diff --git a/src/pages/settings/components/Theming/Backgrounds/components/EditBackground.tsx b/src/pages/settings/components/Theming/Backgrounds/components/EditBackground.tsx index c8f949d..eb6ad95 100644 --- a/src/pages/settings/components/Theming/Backgrounds/components/EditBackground.tsx +++ b/src/pages/settings/components/Theming/Backgrounds/components/EditBackground.tsx @@ -72,6 +72,8 @@ export function EditBackground({ fileName.length, )}`, }, + }).catch((error) => { + console.error(error); }); } else { mutateAsync({ @@ -81,6 +83,8 @@ export function EditBackground({ fileName, newFileName: rename, }, + }).catch((error) => { + console.error(error); }); } handleEditBackgroundModalClose(); diff --git a/src/pages/settings/components/Theming/ThemePlaylists/ThemePlaylists.tsx b/src/pages/settings/components/Theming/ThemePlaylists/ThemePlaylists.tsx index d5a71b2..c69a42e 100644 --- a/src/pages/settings/components/Theming/ThemePlaylists/ThemePlaylists.tsx +++ b/src/pages/settings/components/Theming/ThemePlaylists/ThemePlaylists.tsx @@ -41,7 +41,7 @@ export function ThemePlaylists() { const [opened, { open, close }] = useDisclosure(false); const [selectedPlaylist, setSelectedPlaylist] = useState(defaultPlaylist); - const { currentThemePlaylist, theme, isMobile } = useCommonHooks(); + const { settings, theme, isMobile } = useCommonHooks(); const [isLoading, setIsLoading] = useState(false); const handleOpen = useCallback( @@ -58,10 +58,12 @@ export function ThemePlaylists() { }, [close]); const handleSavePlaylist = useCallback(() => { - void mutateAsync({ + mutateAsync({ method: selectedPlaylist?.id === undefined ? 'POST' : 'PATCH', endpoint: themePlaylistsEndpoint, body: selectedPlaylist ?? {}, + }).catch((error) => { + console.error(error); }); close(); }, [selectedPlaylist, mutateAsync, themePlaylistsEndpoint, close]); @@ -189,7 +191,7 @@ export function ThemePlaylists() { - {'All' === currentThemePlaylist && ( + {'All' === settings.currentThemePlaylist && ( - {'Backgrounds' === currentThemePlaylist && ( + {'Backgrounds' === settings.currentThemePlaylist && ( - {'No Backgrounds' === currentThemePlaylist && ( + {'No Backgrounds' === settings.currentThemePlaylist && ( - {'Time of Day' === currentThemePlaylist && ( + {'Time of Day' === settings.currentThemePlaylist && ( { return ( - {cardPlaylist.name === currentThemePlaylist && ( + {cardPlaylist.name === settings.currentThemePlaylist && ( { - setCurrentThemePlaylist(cardPlaylist.name); - setThemeName('random'); + updateSetting('currentThemePlaylist', cardPlaylist.name); + updateSetting('theme', 'random'); }} disabled={themeList.length === 0} > diff --git a/src/pages/settings/components/Theming/ThemePlaylists/components/ThemePlaylistStack.tsx b/src/pages/settings/components/Theming/ThemePlaylists/components/ThemePlaylistStack.tsx index 3504347..4e13811 100644 --- a/src/pages/settings/components/Theming/ThemePlaylists/components/ThemePlaylistStack.tsx +++ b/src/pages/settings/components/Theming/ThemePlaylists/components/ThemePlaylistStack.tsx @@ -25,8 +25,7 @@ export function ThemePlaylistStack({ setPressed(true); }); const [hover, setHover] = useState(false); - const { setThemeName, setCurrentThemePlaylist, handleDelete, currentUser } = - useCommonHooks(); + const { settings, updateSetting, handleDelete } = useCommonHooks(); const [indexOffset, setIndexOffset] = useState(0); const [movingIndex, setMovingIndex] = useState(0); const missingTheme = { @@ -41,7 +40,7 @@ export function ThemePlaylistStack({ randomEnabled: 1, textShadowsEnabled: 0, appShadowsEnabled: 0, - themeFont: currentUser.defaultFont, + themeFont: settings.defaultFont, }; const [topTheme, setTopTheme] = useState(missingTheme); const defaultLists = ['All', 'Backgrounds', 'No Backgrounds']; @@ -156,8 +155,8 @@ export function ThemePlaylistStack({ borderRadius: '100%', }} onClick={() => { - setCurrentThemePlaylist(cardPlaylist.name); - setThemeName('random'); + updateSetting('currentThemePlaylist', cardPlaylist.name); + updateSetting('theme', 'random'); }} > {modalOpened && ( diff --git a/src/pages/settings/components/Theming/Themes/ThemeCard/ThemeCard.tsx b/src/pages/settings/components/Theming/Themes/ThemeCard/ThemeCard.tsx index 582ebef..3731dda 100644 --- a/src/pages/settings/components/Theming/Themes/ThemeCard/ThemeCard.tsx +++ b/src/pages/settings/components/Theming/Themes/ThemeCard/ThemeCard.tsx @@ -27,8 +27,7 @@ export function ThemeCard({ }) { const { hovered, ref: hoverRef } = useHover(); const [modalOpened, { open: openModal, close: closeModal }] = useDisclosure(false); - const { currentTheme, setCurrentTheme, setCurrentThemePlaylist, handleDelete } = - useCommonHooks(); + const { settings, updateSetting, handleDelete } = useCommonHooks(); const [hoverPreview, setHoverPreview] = useDebouncedState(false, 1000); const [transition, setTransition] = useDebouncedState(false, 200); @@ -113,7 +112,7 @@ export function ThemeCard({