Skip to content

fix: improve local login UX#2849

Open
fallenbagel wants to merge 9 commits intodevelopfrom
fallenbagel/fix/local-login-ux
Open

fix: improve local login UX#2849
fallenbagel wants to merge 9 commits intodevelopfrom
fallenbagel/fix/local-login-ux

Conversation

@fallenbagel
Copy link
Copy Markdown
Collaborator

@fallenbagel fallenbagel commented Apr 9, 2026

Description

This PR addresses several UX pain points around local login, particularly for Jellyfin/Emby instances where usernames are used in place of email addresses.

The local login form placeholder has been changed from "Email Address / Username" to just "Email Address", with a contextual hint shown for Jellyfin/Emby instances explaining that users without an email set can use their username.

The password settings page now clarifies that the password is for local login and is separate from the media server password.

Admins are now warned when importing users that imported accounts don't have a local password set, and a warning is shown on the user settings page when disabling media server sign-in, since this could lock out users who haven't set a local password.

The local login error message now distinguishes between invalid credentials and actual server errors instead of showing a generic "Something went wrong" for both.

The email required warning has been moved from the bottom of the sidebar (where it was easy to miss and invisible on mobile) to a banner in the main content area. Clicking the banner opens a modal that lets users set their email directly without navigating away from the current page.

How Has This Been Tested?

  • Dev server actively checking all the changes live

Screenshots / Logs (if applicable)

  • Local login (placeholder and hint)
image
  • Password settings page:
image
  • Warning when importing users
image
  • Warning when disabling Media Server login in Settings > Users
image
  • Local login invalid credentials
image
  • User warning when require email is checked in settings > notifications > email:
image
  • Popup for entering email address:
image

Checklist:

  • I have read and followed the contribution guidelines.
  • Disclosed any use of AI (see our policy)
  • I have updated the documentation accordingly.
  • All new and existing tests passed.
  • Successful build pnpm build
  • Translation keys pnpm i18n:extract
  • Database migration (if required)

Summary by CodeRabbit

  • New Features

    • Profile incomplete warning is now shown inline above content with a quick-action button that opens an Add Email modal; saving email validates and shows success/error toasts and refreshes profile data.
    • Login now distinguishes credential errors and shows Jellyfin/Emby username guidance when applicable.
    • Import flows now warn that imported users may lack passwords (Jellyfin/Emby/Plex).
  • Documentation

    • Clarified password/setup copy and added new localized strings for these flows.

Replace confusing "Email Address / Username" placeholder with just"Email Address" and add a
contextual hint for Jellyfin/Emby instancesexplaining that users without an email set can use their
username.
Add a description below the Password heading explaining that thispassword is for the local login
form and is separate from the mediaserver password.
…ling media server login

Show a warning toast after importing Plex/Jellyfin/Emby users thatimported accounts do not have a
local password set. Also show awarning on the user settings page when media server sign-in
isdisabled, as affected users may be locked out.
Distinguish between wrong credentials (403) and actual server errors(500) in the local login form
instead of showing a generic "Something went wrong" message for both.
…odal

Move UserWarnings from the sidebar to the main layout so it is visibleon all screen sizes. Rewrite
AddEmailModal to use the profile settingsendpoint instead of Jellyfin auth, allowing users to set
their emaildirectly from the banner without navigating away.

fix #1108
@fallenbagel fallenbagel requested a review from a team as a code owner April 9, 2026 17:30
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 9, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: b5f1e6b7-a1db-4c6a-b3ce-91ef14161f71

📥 Commits

Reviewing files that changed from the base of the PR and between 861178e and 5cafbd7.

📒 Files selected for processing (3)
  • src/components/Login/AddEmailModal.tsx
  • src/components/UserList/PlexImportModal.tsx
  • src/i18n/locale/en.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/components/UserList/PlexImportModal.tsx
  • src/components/Login/AddEmailModal.tsx
  • src/i18n/locale/en.json

📝 Walkthrough

Walkthrough

UserWarnings removed from the Sidebar and added into the main Layout; UserWarnings now opens an in-place AddEmailModal to collect missing emails. AddEmailModal, login, import modals, settings, and i18n strings were updated for email-driven flows and improved error/toast handling.

Changes

Cohort / File(s) Summary
Layout & UserWarnings
src/components/Layout/Sidebar/index.tsx, src/components/Layout/index.tsx, src/components/Layout/UserWarnings/index.tsx
Removed UserWarnings from the Sidebar, inserted <UserWarnings /> into the main Layout, and refactored UserWarnings to be prop-less and open an in-place AddEmailModal via a button.
Add Email Modal
src/components/Login/AddEmailModal.tsx
Reworked to use authenticated user (removed username/password props), fetch/update user settings via API, call mutate/revalidate, and surface toast errors (including explicit "email already taken"). Fixed transition class typo and simplified Formik render.
Login UX
src/components/Login/LocalLogin.tsx
Changed email placeholder to "Email", added Jellyfin/Emby-specific hint, and improved error messages by distinguishing 403 credential errors from generic failures.
Import Modals
src/components/UserList/JellyfinImportModal.tsx, src/components/UserList/PlexImportModal.tsx
After successful imports, added persistent warning toasts indicating imported users may lack passwords (new i18n keys).
Settings & Password UI
src/components/Settings/SettingsUsers/index.tsx, src/components/UserProfile/UserSettings/UserPasswordChange/index.tsx
Added a warning Alert when disabling media-server sign-in may lock users out; added descriptive/localized password messaging using applicationTitle.
Localization
src/i18n/locale/en.json
Added multiple i18n keys (e.g., user warnings, login, import warnings, save errors) and updated the login description to reflect email collection and use.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Layout as Layout Component
    participant UserWarnings as UserWarnings Component
    participant Modal as AddEmailModal
    participant API as Backend API
    participant UserCtx as User Context

    User->>Layout: Load page
    Layout->>UserWarnings: Render UserWarnings
    UserWarnings->>UserWarnings: Detect profile incomplete
    User->>UserWarnings: Click "Profile is incomplete" button
    UserWarnings->>Modal: Open AddEmailModal
    User->>Modal: Submit email
    Modal->>API: GET /api/v1/user/:id/settings/main
    API-->>Modal: Return settings payload
    Modal->>API: POST /api/v1/user/:id/settings/main (with updated email)
    alt Success
        API-->>Modal: 200 OK
        Modal->>UserCtx: call revalidate()/mutate
        UserCtx-->>Modal: user/settings refreshed
        Modal->>User: show success toast & close
    else InvalidEmail
        API-->>Modal: error (InvalidEmail)
        Modal->>User: show "email already taken" toast
    else Other error
        API-->>Modal: error
        Modal->>User: show generic failure toast
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I nudged a button, a modal in sight,
A tiny form glowing, ready to write.
Save, revalidate — hop, hop, hooray!
Emails now captured, no more delay.
🥕🫧

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main objective of improving the local login user experience by addressing email collection and login clarity.
Linked Issues check ✅ Passed All code changes directly implement requirements from #1108 (email modal popup) and #2519 (login field simplification), including contextual hints, profile completion warnings, and improved error messaging.
Out of Scope Changes check ✅ Passed All changes are within scope of the linked issues and PR objectives; no extraneous modifications detected beyond the defined local login UX improvements.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions bot added the i18n-out-of-sync User forgot to run pnpm i18n:extract label Apr 9, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 9, 2026

The i18n check failed because translation messages are out of sync.

This usually happens when you've added or modified translation strings in your code but haven't updated the translation file.

Please run pnpm i18n:extract and commit the changes.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/Login/AddEmailModal.tsx`:
- Around line 63-70: Add an early guard to avoid calling axios.get/post and
mutate when user or user.id is missing: check the local AddEmailModal handler
(where axios.get(`/api/v1/user/${user?.id}/settings/main`), axios.post(...), and
mutate(...) are invoked) and return early or throw if user or user.id is falsy
before making the API requests; ensure you reference the same variables (user,
user.id, values.email) and only call axios.get/axios.post/mutate when user.id is
defined.

In `@src/components/Login/LocalLogin.tsx`:
- Line 25: Update the credential error message in the LocalLogin component by
changing the credentialerror string to a neutral form that supports username
fallback (e.g., "The username or password is incorrect."); locate the
credentialerror entry in the LocalLogin.tsx translations/labels object and
replace the current "The email address or password is incorrect." text with the
new neutral wording, ensuring any other usages of credentialerror remain
compatible.

In `@src/i18n/locale/en.json`:
- Line 1370: The message key components.UserList.importedUsersNoPassword
contains a hardcoded "Plex sign-in"; update the string to use the
{mediaServerName} placeholder instead (same pattern as
disabledMediaServerLoginWarning) so it correctly displays the media server name
for Plex/Jellyfin/Emby imports; locate the key
components.UserList.importedUsersNoPassword in src/i18n/locale/en.json and
replace the literal text "Plex sign-in" with "{mediaServerName} sign-in" (or the
equivalent placement) while preserving the existing {applicationTitle}
placeholder and punctuation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0f2a944c-a146-47bc-acad-fbecd8bcfcc8

📥 Commits

Reviewing files that changed from the base of the PR and between 061121c and ea7238e.

📒 Files selected for processing (10)
  • src/components/Layout/Sidebar/index.tsx
  • src/components/Layout/UserWarnings/index.tsx
  • src/components/Layout/index.tsx
  • src/components/Login/AddEmailModal.tsx
  • src/components/Login/LocalLogin.tsx
  • src/components/Settings/SettingsUsers/index.tsx
  • src/components/UserList/JellyfinImportModal.tsx
  • src/components/UserList/PlexImportModal.tsx
  • src/components/UserProfile/UserSettings/UserPasswordChange/index.tsx
  • src/i18n/locale/en.json
💤 Files with no reviewable changes (1)
  • src/components/Layout/Sidebar/index.tsx

@github-actions github-actions bot removed the i18n-out-of-sync User forgot to run pnpm i18n:extract label Apr 9, 2026
@seerr-automation-bot seerr-automation-bot added this to the v3.2.0 milestone Apr 9, 2026
Copy link
Copy Markdown
Member

@gauthier-th gauthier-th left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice enhancement

@fallenbagel fallenbagel enabled auto-merge (squash) April 13, 2026 03:17
typeof errors.email === 'string' && (
<div className="error">{errors.email}</div>
)}
{(settings.currentSettings.mediaServerType ===
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any way this message could be displayed only if this is actually a possible concern (i.e. only if there are users that don't have an email set)?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will have to query the db for all users and check if the email is valid or not

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, good point, it might not be worth the tradeoff there. Just thought it might be a bit cleaner.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, good point, it might not be worth the tradeoff there. Just thought it might be a bit cleaner.

I also thought of doing that. But that just creates extra latency/performance overhead just for a hint helper text 😔

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Popup to enter Email Address

4 participants