From e10cbf9e8f0f133ce84a9b647a919afac361df38 Mon Sep 17 00:00:00 2001 From: schroda <50052685+schroda@users.noreply.github.com> Date: Mon, 15 Jan 2024 23:48:11 +0100 Subject: [PATCH] Add extension settings screen (#557) --- src/App.tsx | 4 +- src/i18n/locale/en.json | 3 +- src/screens/Extensions.tsx | 2 +- src/screens/Settings.tsx | 19 ++-- src/screens/settings/ExtensionSettings.tsx | 114 +++++++++++++++++++++ src/screens/settings/ServerSettings.tsx | 87 +--------------- 6 files changed, 129 insertions(+), 100 deletions(-) create mode 100644 src/screens/settings/ExtensionSettings.tsx diff --git a/src/App.tsx b/src/App.tsx index badfbd45..a11c9c8e 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -33,9 +33,9 @@ import { LibrarySettings } from '@/screens/settings/LibrarySettings'; import { DefaultNavBar } from '@/components/navbar/DefaultNavBar'; import { DownloadSettings } from '@/screens/settings/DownloadSettings.tsx'; import { ServerSettings } from '@/screens/settings/ServerSettings.tsx'; -import { WebUISettings } from '@/screens/settings/WebUISettings.tsx'; import { ServerUpdateChecker } from '@/components/settings/ServerUpdateChecker.tsx'; import { requestManager } from '@/lib/requests/RequestManager.ts'; +import { ExtensionSettings } from '@/screens/settings/ExtensionSettings.tsx'; if (process.env.NODE_ENV !== 'production') { // Adds messages only in a dev environment @@ -98,7 +98,7 @@ export const App: React.FC = () => ( } /> } /> } /> - } /> + } /> {/* Manga Routes */} diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json index 67b24495..4d5206d2 100644 --- a/src/i18n/locale/en.json +++ b/src/i18n/locale/en.json @@ -255,7 +255,8 @@ "title": "Extension repositories" } } - } + }, + "title": "Extension Settings" }, "state": { "label": { diff --git a/src/screens/Extensions.tsx b/src/screens/Extensions.tsx index 503c574b..5e484b1b 100644 --- a/src/screens/Extensions.tsx +++ b/src/screens/Extensions.tsx @@ -213,7 +213,7 @@ export function Extensions() { return ( {t('extension.label.add_repository_info')} - diff --git a/src/screens/Settings.tsx b/src/screens/Settings.tsx index 2acc3e89..6b92da4f 100644 --- a/src/screens/Settings.tsx +++ b/src/screens/Settings.tsx @@ -17,7 +17,6 @@ import ListItem from '@mui/material/ListItem'; import ListItemIcon from '@mui/material/ListItemIcon'; import ListItemText from '@mui/material/ListItemText'; import Switch from '@mui/material/Switch'; -import FavoriteIcon from '@mui/icons-material/Favorite'; import { Link, ListItemButton, MenuItem, Select } from '@mui/material'; import { useTranslation } from 'react-i18next'; import LanguageIcon from '@mui/icons-material/Language'; @@ -27,6 +26,7 @@ import ViewModuleIcon from '@mui/icons-material/ViewModule'; import DnsIcon from '@mui/icons-material/Dns'; import WebIcon from '@mui/icons-material/Web'; import DeleteForeverIcon from '@mui/icons-material/DeleteForever'; +import ExploreOutlinedIcon from '@mui/icons-material/ExploreOutlined'; import { langCodeToName } from '@/util/language'; import { useLocalStorage } from '@/util/useLocalStorage'; import { ListItemLink } from '@/components/util/ListItemLink'; @@ -46,7 +46,6 @@ export function Settings() { }, [t]); const { darkTheme, setDarkTheme } = useContext(DarkTheme); - const [showNsfw, setShowNsfw] = useLocalStorage('showNsfw', true); const DEFAULT_ITEM_WIDTH = 300; const itemWidthIcon = useMemo(() => , []); @@ -116,16 +115,6 @@ export function Settings() { showSlider handleUpdate={setItemWidth} /> - - - - - - setShowNsfw(!showNsfw)} /> - @@ -162,6 +151,12 @@ export function Settings() { secondary={t('settings.clear_cache.label.description')} /> + + + + + + diff --git a/src/screens/settings/ExtensionSettings.tsx b/src/screens/settings/ExtensionSettings.tsx new file mode 100644 index 00000000..9d7aea4e --- /dev/null +++ b/src/screens/settings/ExtensionSettings.tsx @@ -0,0 +1,114 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ + +import { Trans, useTranslation } from 'react-i18next'; +import { useContext, useEffect } from 'react'; +import List from '@mui/material/List'; +import ListItem from '@mui/material/ListItem'; +import ListItemText from '@mui/material/ListItemText'; +import Switch from '@mui/material/Switch'; +import { NavBarContext, useSetDefaultBackTo } from '@/components/context/NavbarContext.tsx'; +import { requestManager } from '@/lib/requests/RequestManager.ts'; +import { NumberSetting } from '@/components/settings/NumberSetting.tsx'; +import { MutableListSetting } from '@/components/settings/MutableListSetting.tsx'; +import { ServerSettings as GqlServerSettings } from '@/typings.ts'; +import { TextSetting } from '@/components/settings/text/TextSetting.tsx'; +import { useLocalStorage } from '@/util/useLocalStorage.tsx'; + +type ExtensionsSettings = Pick; + +const extractExtensionSettings = (settings: GqlServerSettings): ExtensionsSettings => ({ + maxSourcesInParallel: settings.maxSourcesInParallel, + localSourcePath: settings.localSourcePath, + extensionRepos: settings.extensionRepos, +}); + +export const ExtensionSettings = () => { + const { t } = useTranslation(); + const { setTitle, setAction } = useContext(NavBarContext); + + useSetDefaultBackTo('settings'); + + useEffect(() => { + setTitle(t('extension.settings.title')); + setAction(null); + }, [t]); + + const [showNsfw, setShowNsfw] = useLocalStorage('showNsfw', true); + + const { data } = requestManager.useGetServerSettings(); + const serverSettings = data ? extractExtensionSettings(data.settings) : undefined; + const [mutateSettings] = requestManager.useUpdateServerSettings(); + + const updateSetting = ( + setting: Setting, + value: ExtensionsSettings[Setting], + ) => { + mutateSettings({ variables: { input: { settings: { [setting]: value } } } }); + }; + + return ( + + + + setShowNsfw(!showNsfw)} /> + + updateSetting('maxSourcesInParallel', parallelSources)} + /> + + Suwayomi does not provide any support for 3rd party repositories or extensions! +
+ Use with caution as there could be malicious actors making those repositories. +
+ You as the user need to verify the security and that you trust any repository or extension. + + } + handleChange={(repos) => { + updateSetting('extensionRepos', repos); + requestManager.clearExtensionCache(); + }} + values={serverSettings?.extensionRepos} + addItemButtonTitle={t('extension.settings.repositories.custom.dialog.action.button.add')} + placeholder="https://github.com/MY_ACCOUNT/MY_REPO/tree/repo" + validateItem={(repo) => + !!repo.match( + /https:\/\/(www\.|raw\.)?(github|githubusercontent)\.com\/([^/]+)\/([^/]+)((\/tree|\/blob)?\/([^/\n]*))?(\/([^/\n]*\.json)?)?/g, + ) + } + invalidItemError={t('extension.settings.repositories.custom.error.label.invalid_url')} + /> + updateSetting('localSourcePath', path)} + /> +
+ ); +}; diff --git a/src/screens/settings/ServerSettings.tsx b/src/screens/settings/ServerSettings.tsx index 88939225..df92b527 100644 --- a/src/screens/settings/ServerSettings.tsx +++ b/src/screens/settings/ServerSettings.tsx @@ -6,7 +6,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { useTranslation, Trans } from 'react-i18next'; +import { useTranslation } from 'react-i18next'; import { useContext, useEffect } from 'react'; import { List, ListItem, ListItemText, Switch } from '@mui/material'; import ListSubheader from '@mui/material/ListSubheader'; @@ -16,7 +16,6 @@ import { useLocalStorage } from '@/util/useLocalStorage.tsx'; import { TextSetting } from '@/components/settings/text/TextSetting.tsx'; import { ServerSettings as GqlServerSettings } from '@/typings.ts'; import { NumberSetting } from '@/components/settings/NumberSetting.tsx'; -import { MutableListSetting } from '@/components/settings/MutableListSetting.tsx'; type ServerSettingsType = Pick< GqlServerSettings, @@ -31,12 +30,9 @@ type ServerSettingsType = Pick< | 'basicAuthEnabled' | 'basicAuthUsername' | 'basicAuthPassword' - | 'maxSourcesInParallel' - | 'localSourcePath' - | 'extensionRepos' >; -const extractDownloadSettings = (settings: GqlServerSettings): ServerSettingsType => ({ +const extractServerSettings = (settings: GqlServerSettings): ServerSettingsType => ({ ip: settings.ip, port: settings.port, socksProxyEnabled: settings.socksProxyEnabled, @@ -48,9 +44,6 @@ const extractDownloadSettings = (settings: GqlServerSettings): ServerSettingsTyp basicAuthEnabled: settings.basicAuthEnabled, basicAuthUsername: settings.basicAuthUsername, basicAuthPassword: settings.basicAuthPassword, - maxSourcesInParallel: settings.maxSourcesInParallel, - localSourcePath: settings.localSourcePath, - extensionRepos: settings.extensionRepos, }); export const ServerSettings = () => { @@ -65,7 +58,7 @@ export const ServerSettings = () => { }, [t]); const { data } = requestManager.useGetServerSettings(); - const serverSettings = data ? extractDownloadSettings(data.settings) : undefined; + const serverSettings = data ? extractServerSettings(data.settings) : undefined; const [mutateSettings] = requestManager.useUpdateServerSettings(); const [serverAddress, setServerAddress] = useLocalStorage('serverBaseURL', ''); @@ -99,80 +92,6 @@ export const ServerSettings = () => { placeholder="http://localhost:4567" /> - - {t('settings.server.requests.title')} - - } - > - updateSetting('maxSourcesInParallel', parallelSources)} - /> - - - {t('extension.title')} - - } - > - - - Suwayomi does not provide any support for 3rd party repositories or extensions! - -
- Use with caution as there could be malicious actors making those repositories. -
- You as the user need to verify the security and that you trust any repository or extension. - - } - handleChange={(repos) => { - updateSetting('extensionRepos', repos); - requestManager.clearExtensionCache(); - }} - values={serverSettings?.extensionRepos} - addItemButtonTitle={t('extension.settings.repositories.custom.dialog.action.button.add')} - placeholder="https://github.com/MY_ACCOUNT/MY_REPO/tree/repo" - validateItem={(repo) => - !!repo.match( - /https:\/\/(www\.|raw\.)?(github|githubusercontent)\.com\/([^/]+)\/([^/]+)((\/tree|\/blob)?\/([^/\n]*))?(\/([^/\n]*\.json)?)?/g, - ) - } - invalidItemError={t('extension.settings.repositories.custom.error.label.invalid_url')} - /> -
- - {t('source.local_source.title')} - - } - > - updateSetting('localSourcePath', path)} - /> -