diff --git a/src/components/Login/JellyfinLogin.tsx b/src/components/Login/JellyfinLogin.tsx index ddb8871e..9a5d9424 100644 --- a/src/components/Login/JellyfinLogin.tsx +++ b/src/components/Login/JellyfinLogin.tsx @@ -1,7 +1,3 @@ -import EmbyLogoInverted from '@app/assets/services/emby-inverted.svg'; -import EmbyLogo from '@app/assets/services/emby.svg'; -import JellyfinLogoInverted from '@app/assets/services/jellyfin-icon-only-inverted.svg'; -import JellyfinLogo from '@app/assets/services/jellyfin-icon-only.svg'; import Button from '@app/components/Common/Button'; import Tooltip from '@app/components/Common/Tooltip'; import useSettings from '@app/hooks/useSettings'; @@ -10,7 +6,7 @@ import { MediaServerType, ServerType } from '@server/constants/server'; import axios from 'axios'; import { Field, Form, Formik } from 'formik'; import type React from 'react'; -import { defineMessages, useIntl } from 'react-intl'; +import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; import { useToasts } from 'react-toast-notifications'; import * as Yup from 'yup'; @@ -36,25 +32,35 @@ const messages = defineMessages({ initialsignin: 'Connect', forgotpassword: 'Forgot Password?', servertype: 'Server Type', + back: 'Go back', }); interface JellyfinLoginProps { revalidate: () => void; initial?: boolean; serverType?: MediaServerType; - onServerTypeChange?: (type: MediaServerType) => void; + onCancel: () => void; } const JellyfinLogin: React.FC = ({ revalidate, initial, serverType, - onServerTypeChange, + onCancel, }) => { const toasts = useToasts(); const intl = useIntl(); const settings = useSettings(); + const mediaServerFormatValues = { + mediaServerName: + serverType === MediaServerType.JELLYFIN + ? ServerType.JELLYFIN + : serverType === MediaServerType.EMBY + ? ServerType.EMBY + : 'Media Server', + }; + if (initial) { const LoginSchema = Yup.object().shape({ host: Yup.string() @@ -63,9 +69,10 @@ const JellyfinLogin: React.FC = ({ intl.formatMessage(messages.validationhostformat) ) .required( - intl.formatMessage(messages.validationhostrequired, { - mediaServerName: serverType, - }) + intl.formatMessage( + messages.validationhostrequired, + mediaServerFormatValues + ) ), email: Yup.string() .email(intl.formatMessage(messages.validationemailformat)) @@ -74,20 +81,8 @@ const JellyfinLogin: React.FC = ({ intl.formatMessage(messages.validationusernamerequired) ), password: Yup.string(), - serverType: Yup.string().required( - intl.formatMessage(messages.validationservertyperequired) - ), }); - const mediaServerFormatValues = { - mediaServerName: - serverType === MediaServerType.JELLYFIN - ? ServerType.JELLYFIN - : serverType === MediaServerType.EMBY - ? ServerType.EMBY - : 'Media Server', - }; - return ( = ({ password: '', host: '', email: '', - serverType: '', }} - initialErrors={{ serverType: 'Please select a server type' }} // Initialize errors with an empty object - initialTouched={{ serverType: true }} validationSchema={LoginSchema} onSubmit={async (values) => { try { @@ -131,64 +123,9 @@ const JellyfinLogin: React.FC = ({ } }} > - {({ - errors, - touched, - isSubmitting, - isValid, - values, - setFieldValue, - }) => ( + {({ errors, touched, isSubmitting, isValid }) => (
- -
-
- - -
- {/* Hidden field */} - - {!values.serverType && errors.serverType && ( -
{errors.serverType}
- )} -
@@ -274,7 +211,7 @@ const JellyfinLogin: React.FC = ({
-
+
+ + +
diff --git a/src/components/Setup/SetupLogin.tsx b/src/components/Setup/SetupLogin.tsx index ab5e9cc9..b64795bc 100644 --- a/src/components/Setup/SetupLogin.tsx +++ b/src/components/Setup/SetupLogin.tsx @@ -1,40 +1,37 @@ -import Accordion from '@app/components/Common/Accordion'; +import Button from '@app/components/Common/Button'; import JellyfinLogin from '@app/components/Login/JellyfinLogin'; import PlexLoginButton from '@app/components/PlexLoginButton'; import { useUser } from '@app/hooks/useUser'; -import { MediaServerType, ServerType } from '@server/constants/server'; +import { MediaServerType } from '@server/constants/server'; import axios from 'axios'; import type React from 'react'; import { useEffect, useState } from 'react'; -import { defineMessages, FormattedMessage, useIntl } from 'react-intl'; +import { defineMessages, FormattedMessage } from 'react-intl'; const messages = defineMessages({ - welcome: 'Welcome to Jellyseerr', - signinMessage: 'Get started by signing in', - signinWithJellyfin: 'Use your {mediaServerName} account', - signinWithPlex: 'Use your Plex account', + signin: 'Sign in to your account', + signinWithJellyfin: 'Enter your Jellyfin details', + signinWithEmby: 'Enter your Emby details', + signinWithPlex: 'Enter your Plex details', + back: 'Go back', }); interface LoginWithMediaServerProps { - onComplete: (onComplete: MediaServerType) => void; + serverType: MediaServerType; + onCancel: () => void; + onComplete: () => void; } -const SetupLogin: React.FC = ({ onComplete }) => { +const SetupLogin: React.FC = ({ + serverType, + onCancel, + onComplete, +}) => { const [authToken, setAuthToken] = useState(undefined); const [mediaServerType, setMediaServerType] = useState( MediaServerType.NOT_CONFIGURED ); const { user, revalidate } = useUser(); - const intl = useIntl(); - const [serverType, setserverType] = useState( - undefined - ); - - // Function to handle toggle changes - const handleServerTypeChange = (type: MediaServerType) => { - // Toggle between 'emby' and 'jellyfin' - setserverType(type); - }; // Effect that is triggered when the `authToken` comes back from the Plex OAuth // We take the token and attempt to login. If we get a success message, we will @@ -57,77 +54,60 @@ const SetupLogin: React.FC = ({ onComplete }) => { useEffect(() => { if (user) { - onComplete(mediaServerType); + onComplete(); } }, [user, mediaServerType, onComplete]); return ( -
+
- +
- -
- - {({ openIndexes, handleClick, AccordionContent }) => ( - <> - - -
- { - setMediaServerType(MediaServerType.PLEX); - setAuthToken(authToken); - }} - /> -
-
-
- - -
- -
-
-
- + {serverType === MediaServerType.JELLYFIN ? ( + + ) : serverType === MediaServerType.EMBY ? ( + + ) : ( + )} -
+
+ {serverType === MediaServerType.PLEX && ( + <> +
+ { + setMediaServerType(MediaServerType.PLEX); + setAuthToken(authToken); + }} + /> +
+
+ +
+ + )} + {serverType === MediaServerType.JELLYFIN && ( + + )} + {serverType === MediaServerType.EMBY && ( + + )}
); }; diff --git a/src/components/Setup/index.tsx b/src/components/Setup/index.tsx index f5d824b2..0cf6e5a7 100644 --- a/src/components/Setup/index.tsx +++ b/src/components/Setup/index.tsx @@ -1,3 +1,6 @@ +import EmbyLogo from '@app/assets/services/emby.svg'; +import JellyfinLogo from '@app/assets/services/jellyfin.svg'; +import PlexLogo from '@app/assets/services/plex.svg'; import AppDataWarning from '@app/components/AppDataWarning'; import Badge from '@app/components/Common/Badge'; import Button from '@app/components/Common/Button'; @@ -18,10 +21,16 @@ import useSWR, { mutate } from 'swr'; import SetupLogin from './SetupLogin'; const messages = defineMessages({ + welcome: 'Welcome to Jellyseerr', + subtitle: 'Get started by choosing your media server', + configjellyfin: 'Configure Jellyfin', + configplex: 'Configure Plex', + configemby: 'Configure Emby', setup: 'Setup', finish: 'Finish Setup', finishing: 'Finishing…', continue: 'Continue', + servertype: 'Choose server type', signin: 'Sign In', configuremediaserver: 'Configure Media Server', configureservices: 'Configure Services', @@ -90,35 +99,103 @@ const Setup = () => { > 1} /> 2} /> 3} + /> +
{currentStep === 1 && ( - { - setMediaServerType(mServerType); - setCurrentStep(2); - }} - /> +
+
+ {intl.formatMessage(messages.welcome)} +
+
+ {intl.formatMessage(messages.subtitle)} +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
)} {currentStep === 2 && ( -
+ { + setMediaServerType(MediaServerType.NOT_CONFIGURED); + setCurrentStep(1); + }} + onComplete={() => setCurrentStep(3)} + /> + )} + {currentStep === 3 && ( +
{mediaServerType === MediaServerType.PLEX ? ( setMediaServerSettingsComplete(true)} @@ -141,7 +218,7 @@ const Setup = () => { @@ -150,7 +227,7 @@ const Setup = () => {
)} - {currentStep === 3 && ( + {currentStep === 4 && (
diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json index 71126cc2..ded24995 100644 --- a/src/i18n/locale/en.json +++ b/src/i18n/locale/en.json @@ -217,8 +217,9 @@ "components.Layout.UserWarnings.passwordRequired": "A password is required.", "components.Layout.VersionStatus.commitsbehind": "{commitsBehind} {commitsBehind, plural, one {commit} other {commits}} behind", "components.Layout.VersionStatus.outofdate": "Out of Date", - "components.Layout.VersionStatus.streamdevelop": "Overseerr Develop", - "components.Layout.VersionStatus.streamstable": "Overseerr Stable", + "components.Layout.VersionStatus.streamdevelop": "Jellyseerr Develop", + "components.Layout.VersionStatus.streamstable": "Jellyseerr Stable", + "components.Login.back": "Go back", "components.Login.credentialerror": "The username or password is incorrect.", "components.Login.description": "Since this is your first time logging into {applicationName}, you are required to add a valid email address.", "components.Login.email": "Email Address", @@ -231,6 +232,7 @@ "components.Login.password": "Password", "components.Login.save": "Add", "components.Login.saving": "Adding…", + "components.Login.servertype": "Server Type", "components.Login.signin": "Sign In", "components.Login.signingin": "Signing In…", "components.Login.signinheader": "Sign in to continue", @@ -246,6 +248,7 @@ "components.Login.validationhostformat": "Valid URL required", "components.Login.validationhostrequired": "{mediaServerName} URL required", "components.Login.validationpasswordrequired": "You must provide a password", + "components.Login.validationservertyperequired": "Please select a server type", "components.Login.validationusernamerequired": "Username required", "components.ManageSlideOver.alltime": "All Time", "components.ManageSlideOver.downloadstatus": "Downloads", @@ -582,7 +585,7 @@ "components.Settings.Notifications.NotificationsPushbullet.validationAccessTokenRequired": "You must provide an access token", "components.Settings.Notifications.NotificationsPushbullet.validationTypes": "You must select at least one notification type", "components.Settings.Notifications.NotificationsPushover.accessToken": "Application API Token", - "components.Settings.Notifications.NotificationsPushover.accessTokenTip": "Register an application for use with Overseerr", + "components.Settings.Notifications.NotificationsPushover.accessTokenTip": "Register an application for use with Jellyseerr", "components.Settings.Notifications.NotificationsPushover.agentenabled": "Enable Agent", "components.Settings.Notifications.NotificationsPushover.deviceDefault": "Device Default", "components.Settings.Notifications.NotificationsPushover.pushoversettingsfailed": "Pushover notification settings failed to save.", @@ -607,7 +610,7 @@ "components.Settings.Notifications.NotificationsSlack.webhookUrl": "Webhook URL", "components.Settings.Notifications.NotificationsSlack.webhookUrlTip": "Create an Incoming Webhook integration", "components.Settings.Notifications.NotificationsWebPush.agentenabled": "Enable Agent", - "components.Settings.Notifications.NotificationsWebPush.httpsRequirement": "In order to receive web push notifications, Overseerr must be served over HTTPS.", + "components.Settings.Notifications.NotificationsWebPush.httpsRequirement": "In order to receive web push notifications, Jellyseerr must be served over HTTPS.", "components.Settings.Notifications.NotificationsWebPush.toastWebPushTestFailed": "Web push test notification failed to send.", "components.Settings.Notifications.NotificationsWebPush.toastWebPushTestSending": "Sending web push test notification…", "components.Settings.Notifications.NotificationsWebPush.toastWebPushTestSuccess": "Web push test notification sent!", @@ -633,7 +636,7 @@ "components.Settings.Notifications.authPass": "SMTP Password", "components.Settings.Notifications.authUser": "SMTP Username", "components.Settings.Notifications.botAPI": "Bot Authorization Token", - "components.Settings.Notifications.botApiTip": "Create a bot for use with Overseerr", + "components.Settings.Notifications.botApiTip": "Create a bot for use with Jellyseerr", "components.Settings.Notifications.botAvatarUrl": "Bot Avatar URL", "components.Settings.Notifications.botUsername": "Bot Username", "components.Settings.Notifications.botUsernameTip": "Allow users to also start a chat with your bot and configure their own notifications", @@ -748,11 +751,11 @@ "components.Settings.SettingsAbout.githubdiscussions": "GitHub Discussions", "components.Settings.SettingsAbout.helppaycoffee": "Help Pay for Coffee", "components.Settings.SettingsAbout.outofdate": "Out of Date", - "components.Settings.SettingsAbout.overseerrinformation": "About Overseerr", + "components.Settings.SettingsAbout.overseerrinformation": "About Jellyseerr", "components.Settings.SettingsAbout.preferredmethod": "Preferred", - "components.Settings.SettingsAbout.runningDevelop": "You are running the develop branch of Overseerr, which is only recommended for those contributing to development or assisting with bleeding-edge testing.", - "components.Settings.SettingsAbout.supportoverseerr": "Support Overseerr", + "components.Settings.SettingsAbout.runningDevelop": "You are running the develop branch of Jellyseerr, which is only recommended for those contributing to development or assisting with bleeding-edge testing.", "components.Settings.SettingsAbout.supportjellyseerr": "Support Jellyseerr", + "components.Settings.SettingsAbout.supportoverseerr": "Support Overseerr", "components.Settings.SettingsAbout.timezone": "Time Zone", "components.Settings.SettingsAbout.totalmedia": "Total Media", "components.Settings.SettingsAbout.totalrequests": "Total Requests", @@ -760,7 +763,7 @@ "components.Settings.SettingsAbout.version": "Version", "components.Settings.SettingsJobsCache.availability-sync": "Media Availability Sync", "components.Settings.SettingsJobsCache.cache": "Cache", - "components.Settings.SettingsJobsCache.cacheDescription": "Overseerr caches requests to external API endpoints to optimize performance and avoid making unnecessary API calls.", + "components.Settings.SettingsJobsCache.cacheDescription": "Jellyseerr caches requests to external API endpoints to optimize performance and avoid making unnecessary API calls.", "components.Settings.SettingsJobsCache.cacheflushed": "{cachename} cache flushed.", "components.Settings.SettingsJobsCache.cachehits": "Hits", "components.Settings.SettingsJobsCache.cachekeys": "Total Keys", @@ -781,7 +784,7 @@ "components.Settings.SettingsJobsCache.flushcache": "Flush Cache", "components.Settings.SettingsJobsCache.image-cache-cleanup": "Image Cache Cleanup", "components.Settings.SettingsJobsCache.imagecache": "Image Cache", - "components.Settings.SettingsJobsCache.imagecacheDescription": "When enabled in settings, Overseerr will proxy and cache images from pre-configured external sources. Cached images are saved into your config folder. You can find the files in {appDataPath}/cache/images.", + "components.Settings.SettingsJobsCache.imagecacheDescription": "When enabled in settings, Jellyseerr will proxy and cache images from pre-configured external sources. Cached images are saved into your config folder. You can find the files in {appDataPath}/cache/images.", "components.Settings.SettingsJobsCache.imagecachecount": "Images Cached", "components.Settings.SettingsJobsCache.imagecachesize": "Total Cache Size", "components.Settings.SettingsJobsCache.jellyfin-full-scan": "Jellyfin Full Library Scan", @@ -791,7 +794,7 @@ "components.Settings.SettingsJobsCache.jobcancelled": "{jobname} canceled.", "components.Settings.SettingsJobsCache.jobname": "Job Name", "components.Settings.SettingsJobsCache.jobs": "Jobs", - "components.Settings.SettingsJobsCache.jobsDescription": "Overseerr performs certain maintenance tasks as regularly-scheduled jobs, but they can also be manually triggered below. Manually running a job will not alter its schedule.", + "components.Settings.SettingsJobsCache.jobsDescription": "Jellyseerr performs certain maintenance tasks as regularly-scheduled jobs, but they can also be manually triggered below. Manually running a job will not alter its schedule.", "components.Settings.SettingsJobsCache.jobsandcache": "Jobs & Cache", "components.Settings.SettingsJobsCache.jobstarted": "{jobname} started.", "components.Settings.SettingsJobsCache.jobtype": "Type", @@ -832,7 +835,7 @@ "components.Settings.SettingsMain.csrfProtectionTip": "Set external API access to read-only (requires HTTPS)", "components.Settings.SettingsMain.general": "General", "components.Settings.SettingsMain.generalsettings": "General Settings", - "components.Settings.SettingsMain.generalsettingsDescription": "Configure global and default settings for Overseerr.", + "components.Settings.SettingsMain.generalsettingsDescription": "Configure global and default settings for Jellyseerr.", "components.Settings.SettingsMain.hideAvailable": "Hide Available Media", "components.Settings.SettingsMain.locale": "Display Language", "components.Settings.SettingsMain.originallanguage": "Discover Language", @@ -845,7 +848,7 @@ "components.Settings.SettingsMain.toastSettingsFailure": "Something went wrong while saving settings.", "components.Settings.SettingsMain.toastSettingsSuccess": "Settings saved successfully!", "components.Settings.SettingsMain.trustProxy": "Enable Proxy Support", - "components.Settings.SettingsMain.trustProxyTip": "Allow Overseerr to correctly register client IP addresses behind a proxy", + "components.Settings.SettingsMain.trustProxyTip": "Allow Jellyseerr to correctly register client IP addresses behind a proxy", "components.Settings.SettingsMain.validationApplicationTitle": "You must provide an application title", "components.Settings.SettingsMain.validationApplicationUrl": "You must provide a valid URL", "components.Settings.SettingsMain.validationApplicationUrlTrailingSlash": "URL must not end in a trailing slash", @@ -937,6 +940,7 @@ "components.Settings.hostname": "Hostname or IP Address", "components.Settings.internalUrl": "Internal URL", "components.Settings.is4k": "4K", + "components.Settings.jellyfinForgotPasswordUrl": "Forgot Password URL", "components.Settings.jellyfinSettings": "{mediaServerName} Settings", "components.Settings.jellyfinSettingsDescription": "Optionally configure the internal and external endpoints for your {mediaServerName} server. In most cases, the external URL is different to the internal URL. A custom password reset URL can also be set for {mediaServerName} login, in case you would like to redirect to a different password reset page.", "components.Settings.jellyfinSettingsFailure": "Something went wrong while saving {mediaServerName} settings.", @@ -947,7 +951,7 @@ "components.Settings.jellyfinsettingsDescription": "Configure the settings for your {mediaServerName} server. {mediaServerName} scans your {mediaServerName} libraries to see what content is available.", "components.Settings.librariesRemaining": "Libraries Remaining: {count}", "components.Settings.manualscan": "Manual Library Scan", - "components.Settings.manualscanDescription": "Normally, this will only be run once every 24 hours. Overseerr will check your Plex server's recently added more aggressively. If this is your first time configuring Plex, a one-time full manual library scan is recommended!", + "components.Settings.manualscanDescription": "Normally, this will only be run once every 24 hours. Jellyseerr will check your Plex server's recently added more aggressively. If this is your first time configuring Plex, a one-time full manual library scan is recommended!", "components.Settings.manualscanDescriptionJellyfin": "Normally, this will only be run once every 24 hours. Jellyseerr will check your {mediaServerName} server's recently added more aggressively. If this is your first time configuring Jellyseerr, a one-time full manual library scan is recommended!", "components.Settings.manualscanJellyfin": "Manual Library Scan", "components.Settings.mediaTypeMovie": "movie", @@ -970,12 +974,12 @@ "components.Settings.notrunning": "Not Running", "components.Settings.plex": "Plex", "components.Settings.plexlibraries": "Plex Libraries", - "components.Settings.plexlibrariesDescription": "The libraries Overseerr scans for titles. Set up and save your Plex connection settings, then click the button below if no libraries are listed.", + "components.Settings.plexlibrariesDescription": "The libraries Jellyseerr scans for titles. Set up and save your Plex connection settings, then click the button below if no libraries are listed.", "components.Settings.plexsettings": "Plex Settings", "components.Settings.plexsettingsDescription": "Configure the settings for your Plex server. Overseerr scans your Plex libraries to determine content availability.", "components.Settings.port": "Port", "components.Settings.radarrsettings": "Radarr Settings", - "components.Settings.restartrequiredTooltip": "Overseerr must be restarted for changes to this setting to take effect", + "components.Settings.restartrequiredTooltip": "Jellyseerr must be restarted for changes to this setting to take effect", "components.Settings.save": "Save Changes", "components.Settings.saving": "Saving…", "components.Settings.scan": "Sync Libraries", @@ -997,7 +1001,7 @@ "components.Settings.syncing": "Syncing", "components.Settings.tautulliApiKey": "API Key", "components.Settings.tautulliSettings": "Tautulli Settings", - "components.Settings.tautulliSettingsDescription": "Optionally configure the settings for your Tautulli server. Overseerr fetches watch history data for your Plex media from Tautulli.", + "components.Settings.tautulliSettingsDescription": "Optionally configure the settings for your Tautulli server. Jellyseerr fetches watch history data for your Plex media from Tautulli.", "components.Settings.timeout": "Timeout", "components.Settings.toastPlexConnecting": "Attempting to connect to Plex…", "components.Settings.toastPlexConnectingFailure": "Failed to connect to Plex.", @@ -1019,17 +1023,24 @@ "components.Settings.webAppUrlTip": "Optionally direct users to the web app on your server instead of the \"hosted\" web app", "components.Settings.webhook": "Webhook", "components.Settings.webpush": "Web Push", + "components.Setup.back": "Go back", + "components.Setup.configemby": "Configure Emby", + "components.Setup.configjellyfin": "Configure Jellyfin", + "components.Setup.configplex": "Configure Plex", "components.Setup.configuremediaserver": "Configure Media Server", "components.Setup.configureservices": "Configure Services", "components.Setup.continue": "Continue", "components.Setup.finish": "Finish Setup", "components.Setup.finishing": "Finishing…", "components.Setup.scanbackground": "Scanning will run in the background. You can continue the setup process in the meantime.", + "components.Setup.servertype": "Choose server type", "components.Setup.setup": "Setup", - "components.Setup.signin": "Sign In", - "components.Setup.signinMessage": "Get started by signing in", - "components.Setup.signinWithJellyfin": "Use your {mediaServerName} account", - "components.Setup.signinWithPlex": "Use your Plex account", + "components.Setup.signin": "Sign in to your account", + "components.Setup.signinMessage": "Get started by signing in with your Plex account", + "components.Setup.signinWithEmby": "Enter your Emby details", + "components.Setup.signinWithJellyfin": "Enter your Jellyfin details", + "components.Setup.signinWithPlex": "Enter your Plex details", + "components.Setup.subtitle": "Get started by choosing your media server", "components.Setup.tip": "Tip", "components.Setup.welcome": "Welcome to Jellyseerr", "components.StatusBadge.managemedia": "Manage {mediaType}",