diff --git a/README.md b/README.md index ffcacc7..9842c85 100644 --- a/README.md +++ b/README.md @@ -29,4 +29,6 @@ sudo pm2 start server.cjs # TODO - Image uploads for backgrounds -- Improve mobile \ No newline at end of file +- Improve mobile + +- Reorder/Rearrange Bookmarks/Groups \ No newline at end of file diff --git a/src/pages/settings/components/Applications/Applications.tsx b/src/pages/settings/components/Applications/Applications.tsx index e1c3ea9..ec39b6e 100644 --- a/src/pages/settings/components/Applications/Applications.tsx +++ b/src/pages/settings/components/Applications/Applications.tsx @@ -210,15 +210,24 @@ const ApplicationSettings = () => { style={{ color: theme.primaryColor, backgroundColor: theme.backgroundColor, + width: '500px', }} > - {'Applications are the apps that will be displayed in the homepage.'} + {'Applications are the apps that will be displayed on the homepage.'} { WebkitTextFillColor: 'transparent', }} > - {''} + { + 'Applications contain a name, base url, url, icon and filter. Currently the icon must be the mdi icon name. URLs can contain either http(s):// or not. Base URLs should start with /, otherwise they will cause errors.' + } diff --git a/src/pages/settings/components/Bookmarks/Bookmarks.tsx b/src/pages/settings/components/Bookmarks/Bookmarks.tsx index fa22c6a..2e93c68 100644 --- a/src/pages/settings/components/Bookmarks/Bookmarks.tsx +++ b/src/pages/settings/components/Bookmarks/Bookmarks.tsx @@ -162,6 +162,7 @@ const BookmarkSettings = () => { style={{ color: theme.primaryColor, backgroundColor: theme.backgroundColor, + width: '500px', }} > @@ -169,8 +170,16 @@ const BookmarkSettings = () => { {'Bookmarks are the links that will be displayed on the homepage.'} { WebkitTextFillColor: 'transparent', }} > - {''} + { + 'Bookmarks can only belong to a single category, and will be displayed under that category on the homepage.' + } diff --git a/src/pages/settings/components/Messages/Messages.tsx b/src/pages/settings/components/Messages/Messages.tsx index 404dcd0..53a7e83 100644 --- a/src/pages/settings/components/Messages/Messages.tsx +++ b/src/pages/settings/components/Messages/Messages.tsx @@ -151,14 +151,14 @@ const MessageSettings = () => { style={{ color: theme.primaryColor, backgroundColor: theme.backgroundColor, + width: '500px', }} > - {'Messages may contain any unicode text.'} + {'These custom messages will be displayed in the header on the homepage.'} { }} > { - 'Built-in variables include $firstName and $lastName. To force the text to upper case, use a carat (^), ie, $^firstName.' + 'Built-in variables include $firstName and $lastName. To force the text to upper case, use a carat (^), ie, $^firstName. Messages may contain any unicode text.' } diff --git a/src/pages/settings/components/Search/SearchProviders.tsx b/src/pages/settings/components/Search/SearchProviders.tsx index 34b3c84..fa6b934 100644 --- a/src/pages/settings/components/Search/SearchProviders.tsx +++ b/src/pages/settings/components/Search/SearchProviders.tsx @@ -174,6 +174,7 @@ const SearchProviderSettings = () => { style={{ color: theme.primaryColor, backgroundColor: theme.backgroundColor, + width: '500px', }} > @@ -181,7 +182,6 @@ const SearchProviderSettings = () => { {'Search providers and shortcuts can be configured here.'} { WebkitTextFillColor: 'transparent', }} > - {'Providers can be used in the search bar.'} + { + 'Providers can be used in the search bar. By starting a search with the prefix, it will be redirected to the url of the provider to complete the search.' + } diff --git a/src/pages/settings/components/Theming/ThemeCard.tsx b/src/pages/settings/components/Theming/ThemeCard.tsx index 4cef9bd..bfa27a2 100644 --- a/src/pages/settings/components/Theming/ThemeCard.tsx +++ b/src/pages/settings/components/Theming/ThemeCard.tsx @@ -1,30 +1,40 @@ -import { ActionIcon, Box, Button, Group, Overlay, Stack, Text } from '@mantine/core'; -import { useCommonHooks, useQueryAPI } from 'hooks'; +import { + ActionIcon, + Box, + Button, + Group, + Modal, + Overlay, + Stack, + Text, +} from '@mantine/core'; +import { useDisclosure } from '@mantine/hooks'; +import { useCommonHooks, useMutationAPI, useQueryAPI } from 'hooks'; import { useState } from 'react'; import { FiEdit, FiShuffle, FiTrash, FiX } from 'react-icons/fi'; -import { actionIconClasses } from 'styles'; +import { actionIconClasses, modalClasses } from 'styles'; -function ThemeCard({ - cardTheme, - handleOpen, - handleDeleteTheme, - createTheme, - allThemes, -}: any) { +function ThemeCard({ cardTheme, handleOpen, allThemes }: any) { const { data: themePlaylists } = useQueryAPI({ endpoint: 'api/themePlaylists', }); const [hover, setHover] = useState(false); const [shiftEdit, setShiftEdit] = useState(0); const [shiftShuffle, setShiftShuffle] = useState(0); + const { mutateAsync } = useMutationAPI(); + const [modalOpened, { open: openModal, close: closeModal }] = useDisclosure(false); const { handleThemeChange, currentTheme, setCurrentTheme, theme, + isMobile, currentThemePlaylist, setCurrentThemePlaylist, } = useCommonHooks(); + const handleDelete = (application: any) => { + mutateAsync({ method: 'DELETE', endpoint: 'api/themes', body: application }); + }; return ( setHover(true)} onMouseLeave={() => setHover(false)} > + { + closeModal(); + }} + style={{ + '--color-text-pri': theme.primaryColor, + '--color-text-acc': theme.accentColor, + '--color-background': theme.backgroundColor, + '--color-border': theme.borderColor, + '--color-search-background': theme.searchColor, + '--image-background': `url(${theme.backgroundImage})`, + }} + closeOnEscape + closeOnClickOutside + > + + + + Delete Theme + + + + + Are you sure you want to delete this theme? + {`"${cardTheme.name}"`} + This action cannot be undone! + + + + + + + + { - createTheme({ + mutateAsync({ method: 'PATCH', endpoint: 'api/themes', body: { ...cardTheme, randomEnabled: !cardTheme.randomEnabled }, @@ -299,7 +375,7 @@ function ThemeCard({ handleDeleteTheme(cardTheme)} + onClick={openModal} > diff --git a/src/pages/settings/components/Theming/ThemePlaylistCard.tsx b/src/pages/settings/components/Theming/ThemePlaylistCard.tsx index 537f27d..c34a292 100644 --- a/src/pages/settings/components/Theming/ThemePlaylistCard.tsx +++ b/src/pages/settings/components/Theming/ThemePlaylistCard.tsx @@ -2,30 +2,31 @@ import { ActionIcon, Button, Group, + Modal, Overlay, ScrollArea, Stack, Text, } from '@mantine/core'; -import { useCommonHooks } from 'hooks'; +import { useDisclosure } from '@mantine/hooks'; +import { useCommonHooks, useMutationAPI } from 'hooks'; import { useState } from 'react'; import { FiEdit, FiRefreshCcw, FiTrash } from 'react-icons/fi'; +import { modalClasses } from 'styles'; import ThemeMiniCard from './ThemeMiniCard'; -function ThemePlaylistCard({ - cardPlaylist, - handleOpen, - handleDeletePlaylist, - createPlaylist, - allThemes, -}: any) { +function ThemePlaylistCard({ cardPlaylist, handleOpen, allThemes }: any) { const [hover, setHover] = useState(false); - const { setThemeName, setCurrentThemePlaylist, theme } = useCommonHooks(); + const { setThemeName, setCurrentThemePlaylist, theme, isMobile } = useCommonHooks(); const syncableLists = ['All', 'Backgrounds', 'No Backgrounds']; + const { mutateAsync } = useMutationAPI(); + const [modalOpened, { open: openModal, close: closeModal }] = useDisclosure(false); const themeList = JSON.parse( cardPlaylist.themeList.name === 'Time of Day' ? '[]' : cardPlaylist.themeList, ); - + const handleDelete = (application: any) => { + mutateAsync({ method: 'DELETE', endpoint: 'api/themePlaylists', body: application }); + }; return ( setHover(true)} onMouseLeave={() => setHover(false)} > + { + closeModal(); + }} + style={{ + '--color-text-pri': theme.primaryColor, + '--color-text-acc': theme.accentColor, + '--color-background': theme.backgroundColor, + '--color-border': theme.borderColor, + '--color-search-background': theme.searchColor, + '--image-background': `url(${theme.backgroundImage})`, + }} + closeOnEscape + closeOnClickOutside + > + + + + Delete Theme Playlist + + + + + Are you sure you want to delete this Theme Playlist? + {`"${cardPlaylist.name}"`} + This action cannot be undone! + + + + + + + + { event.stopPropagation(); if (cardPlaylist.name === 'All') { - createPlaylist({ + mutateAsync({ method: 'PATCH', endpoint: 'api/themePlaylists', body: { @@ -84,7 +151,7 @@ function ThemePlaylistCard({ }); } if (cardPlaylist.name === 'Backgrounds') { - createPlaylist({ + mutateAsync({ method: 'PATCH', endpoint: 'api/themePlaylists', body: { @@ -101,7 +168,7 @@ function ThemePlaylistCard({ }); } if (cardPlaylist.name === 'No Backgrounds') { - createPlaylist({ + mutateAsync({ method: 'PATCH', endpoint: 'api/themePlaylists', body: { @@ -160,7 +227,9 @@ function ThemePlaylistCard({ : theme.primaryColor, zIndex: 3, }} - onClick={() => handleDeletePlaylist(cardPlaylist)} + onClick={() => { + openModal(); + }} > diff --git a/src/pages/settings/components/Theming/ThemePlaylists.tsx b/src/pages/settings/components/Theming/ThemePlaylists.tsx index 7eb0b33..acbf9ce 100644 --- a/src/pages/settings/components/Theming/ThemePlaylists.tsx +++ b/src/pages/settings/components/Theming/ThemePlaylists.tsx @@ -1,10 +1,18 @@ -import { Box, Button, Group, Stack, Text } from '@mantine/core'; +import { + ActionIcon, + Box, + Button, + Group, + Highlight, + Popover, + Stack, + Text, +} from '@mantine/core'; import { useDisclosure } from '@mantine/hooks'; -import { modals } from '@mantine/modals'; import { useCommonHooks, useMutationAPI, useQueryAPI } from 'hooks'; import { useState } from 'react'; -import { FiChevronRight, FiPlus } from 'react-icons/fi'; -import { buttonClasses, textClasses } from 'styles'; +import { FiChevronRight, FiHelpCircle, FiPlus } from 'react-icons/fi'; +import { actionIconClasses, buttonClasses, textClasses } from 'styles'; import ThemePlaylistCard from './ThemePlaylistCard'; import ThemePlaylistModal from './ThemePlaylistModal'; @@ -15,8 +23,7 @@ function ThemePlaylists() { const { data: themePlaylists } = useQueryAPI({ endpoint: 'api/themePlaylists', }); - const { mutateAsync: createPlaylist } = useMutationAPI(); - const { mutateAsync: deletePlaylist } = useMutationAPI(); + const { mutateAsync } = useMutationAPI(); const [opened, { open, close }] = useDisclosure(false); const [selectedPlaylist, setSelectedPlaylist] = useState({}); const { currentThemePlaylist, setCurrentThemePlaylist, theme } = useCommonHooks(); @@ -31,7 +38,7 @@ function ThemePlaylists() { }; const handleSavePlaylist = () => { - createPlaylist({ + mutateAsync({ method: selectedPlaylist.id === undefined ? 'POST' : 'PATCH', endpoint: 'api/themePlaylists', body: selectedPlaylist, @@ -39,24 +46,6 @@ function ThemePlaylists() { close(); }; - const openDeleteConfirmModal = (playlist: any) => - modals.openConfirmModal({ - title: 'Are you sure you want to delete this theme playlist?', - labels: { confirm: 'Delete', cancel: 'Cancel' }, - confirmProps: { color: 'red' }, - onConfirm: () => - deletePlaylist({ - method: 'DELETE', - endpoint: 'api/themePlaylists', - body: playlist, - }), - }); - - const handleDeletePlaylist = (playlist: any) => { - openDeleteConfirmModal(playlist); - close(); - }; - return ( <> @@ -74,6 +63,45 @@ function ThemePlaylists() { Theme Playlists + + + + + + + + + + {'Theme playlists can be created here and applied to the homepage.'} + + + { + 'Playlists are lists of themes. They can be enabled either here or in the settings button on the homepage. When a playlist is enabled, it will shuffle the included themes on the homepage. If a theme is part of a playlist, it will appear while the playlist is active, regardless of random/shuffle.' + } + + + +