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.'
+ }
+
+
+
+
@@ -164,11 +190,7 @@ function ThemePlaylists() {
diff --git a/src/pages/settings/components/Theming/Themes.tsx b/src/pages/settings/components/Theming/Themes.tsx
index 94794b4..9b6fff7 100644
--- a/src/pages/settings/components/Theming/Themes.tsx
+++ b/src/pages/settings/components/Theming/Themes.tsx
@@ -1,12 +1,22 @@
-import { Box, Button, Group, Overlay, Stack, Switch, Text } from '@mantine/core';
+import {
+ ActionIcon,
+ Box,
+ Button,
+ Group,
+ Highlight,
+ Overlay,
+ Popover,
+ Stack,
+ Switch,
+ Text,
+} from '@mantine/core';
import { useDisclosure } from '@mantine/hooks';
import { useCommonHooks, useMutationAPI, useQueryAPI } from 'hooks';
import { useEffect, useState } from 'react';
-import { FiChevronRight, FiPlus } from 'react-icons/fi';
+import { FiChevronRight, FiHelpCircle, FiPlus } from 'react-icons/fi';
import '@mantine/core/styles/ModalBase.css';
import '@mantine/core/styles/Modal.css';
-import { modals } from '@mantine/modals';
-import { buttonClasses, textClasses } from 'styles';
+import { actionIconClasses, buttonClasses, textClasses } from 'styles';
import ThemeCard from './ThemeCard';
import ThemeModal from './ThemeModal';
function ThemesSettings() {
@@ -16,8 +26,7 @@ function ThemesSettings() {
const { data: backgroundData, isFetched: isBackgroundFetched } = useQueryAPI({
endpoint: 'api/backgrounds',
});
- const { mutateAsync: createTheme } = useMutationAPI();
- const { mutateAsync: deleteTheme } = useMutationAPI();
+ const { mutateAsync } = useMutationAPI();
const [opened, { open, close }] = useDisclosure(false);
const [colorId, setColorId] = useState('');
const [colorValue, setColorValue] = useState('#000000');
@@ -38,7 +47,7 @@ function ThemesSettings() {
};
const handleSaveTheme = () => {
- createTheme({
+ mutateAsync({
method: selectedTheme.id === undefined ? 'POST' : 'PATCH',
endpoint: 'api/themes',
body: selectedTheme,
@@ -46,20 +55,6 @@ function ThemesSettings() {
close();
};
- const openDeleteConfirmModal = (theme: any) =>
- modals.openConfirmModal({
- title: 'Are you sure you want to delete this theme?',
- labels: { confirm: 'Delete', cancel: 'Cancel' },
- confirmProps: { color: 'red' },
- onConfirm: () =>
- deleteTheme({ method: 'DELETE', endpoint: 'api/themes', body: theme }),
- });
-
- const handleDeleteTheme = (theme: any) => {
- openDeleteConfirmModal(theme);
- close();
- };
-
useEffect(() => {
if (backgroundData && isBackgroundFetched) {
setBackgroundList(['None', ...backgroundData]);
@@ -89,6 +84,45 @@ function ThemesSettings() {
Themes
+
+
+
+
+
+
+
+
+
+ {'Themes can be created here and applied to the homepage.'}
+
+
+ {
+ 'Themes are combinations of 5 colors and a background image, and can be added to a playlist. If a theme has been disabled, it will only be disabled with random/shuffle is enabled. If a theme is part of a playlist, it will appear while the playlist is active, regardless of random/shuffle.'
+ }
+
+
+
+