Skip to content

Allow custom display names#1373

Open
skyfallwastaken wants to merge 1 commit into
mainfrom
codex/allow-display-name-settings
Open

Allow custom display names#1373
skyfallwastaken wants to merge 1 commit into
mainfrom
codex/allow-display-name-settings

Conversation

@skyfallwastaken
Copy link
Copy Markdown
Member

Summary of the problem

Users could not set a custom display name. Their visible name came from synced Slack/GitHub/username data, so provider logins could effectively change it back.

Describe your changes

  • Added a Profile settings display-name form backed by display_name_override.
  • Made User#display_name prefer the override before synced Slack, GitHub, username, or email fallback values.
  • Normalized blank/custom display-name input and added length validation.
  • Updated profile/social/OG display-name callers to rely on the centralized User#display_name behavior.
  • Added controller and model coverage, including Slack sync preserving the custom display name.

Validation:

  • docker compose exec web rails test test/controllers/settings_profile_controller_test.rb
  • docker compose exec web rails test test/models/user_test.rb
  • docker compose exec web bun run check:svelte (passes with two existing warnings in Home/signedIn/IntervalSelectBody.svelte)
  • docker compose exec web env JS_FROM_ROUTES_FORCE=true bin/rake js_from_routes:generate

Screenshots / Media

Not included.

Copilot AI review requested due to automatic review settings May 28, 2026 18:18
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 28, 2026

Greptile Summary

This PR allows users to set a custom display name (display_name_override) that takes precedence over their synced Slack/GitHub/username values. The User#display_name method is updated as the single source of truth, and all callers in the profiles controller and OG image generator are simplified to use it directly.

  • Adds a Display Name settings card (Inertia <Form>, CSRF-safe) with server-side normalization (strips Unicode format characters + whitespace) and an 80-character max-length validation.
  • Ensures Slack profile sync preserves any custom override, and backs the feature with controller and model tests covering persistence, blank-clearing, and over-length rejection.

Confidence Score: 4/5

Safe to merge — the change is well-scoped, backed by tests, and correctly centralizes display-name resolution in User#display_name.

All callers are updated, normalization handles edge cases (blank, format characters), and the Slack sync test confirms the custom override is preserved on re-sync. The only finding is a minor redundant double-presence check in the new display_name logic.

app/models/user.rb — minor redundant double-presence check in the new display_name block.

Important Files Changed

Filename Overview
app/models/user.rb Adds DISPLAY_NAME_MAX_LENGTH constant, a normalize_display_name_override before_validation callback (strips Unicode format chars + whitespace), a max-length validation, and updates display_name to prefer the override. Logic is correct; minor double-presence check.
app/controllers/settings/profile_controller.rb Adds update_display_name action, display_name_params strong-parameter helper, and exposes display_name_max_length + extra user props to the Svelte page. Clean and consistent with existing patterns.
app/controllers/settings/base_controller.rb Adds display_name_override error key to common_props and display_name_override builder to USER_PROP_BUILDERS. Only sent when explicitly requested via keys, so no unintended exposure.
app/javascript/pages/Users/Settings/Profile.svelte Adds a Display Name SectionCard using Inertia's Form component, consistent with the project's form rule. Error display and maxlength binding match the TypeScript types.
app/javascript/pages/Users/Settings/types.ts Adds display_name_override to UserProps and ErrorsProps, updates ProfilePageProps to include the new field and display_name_max_length. Types are accurate and well-typed.
test/controllers/settings_profile_controller_test.rb Adds three controller tests covering: persisting override, clearing blank override, and rejecting over-length names. Good coverage of the main paths.
test/models/user_test.rb Adds three model tests: precedence, normalization, and Slack-sync preservation. Well-scoped and verifies the key invariant that a custom override survives provider re-sync.
app/controllers/profiles_controller.rb Removes the now-redundant display_name_override.presence
app/services/profile_og_image_generator.rb Simplifies display_name memoization to use User#display_name directly, removing the redundant override check.
config/routes.rb Adds a PATCH route for display_name update, consistent with the existing flat-route style used for other profile sub-sections.

Sequence Diagram

sequenceDiagram
    participant Browser
    participant ProfileController as Settings::ProfileController
    participant User as User (model)
    participant DB

    Browser->>ProfileController: PATCH /my/settings/profile/display_name
    ProfileController->>ProfileController: display_name_params (strong params)
    ProfileController->>User: update(display_name_override: "Custom Name")
    User->>User: normalize_display_name_override()
    User->>User: "validates length <= 80"
    alt valid
        User->>DB: UPDATE users SET display_name_override
        ProfileController-->>Browser: 302 redirect
    else invalid
        User-->>ProfileController: errors
        ProfileController-->>Browser: 422 Unprocessable Entity
    end
Loading
Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
app/models/user.rb:312-313
Redundant double-presence check: `display_name_override.presence` already returns `nil` when the value is blank, so `name.present?` on the next line always equals `!name.nil?`. The guard can be collapsed to a single expression, consistent with the natural reading of the method.

```suggestion
    return display_name_override if display_name_override.present?
```

Reviews (1): Last reviewed commit: "Allow custom display names" | Re-trigger Greptile

Comment thread app/models/user.rb
Comment on lines +312 to +313
name = display_name_override.presence
return name if name.present?
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.

P2 Redundant double-presence check: display_name_override.presence already returns nil when the value is blank, so name.present? on the next line always equals !name.nil?. The guard can be collapsed to a single expression, consistent with the natural reading of the method.

Suggested change
name = display_name_override.presence
return name if name.present?
return display_name_override if display_name_override.present?
Prompt To Fix With AI
This is a comment left during a code review.
Path: app/models/user.rb
Line: 312-313

Comment:
Redundant double-presence check: `display_name_override.presence` already returns `nil` when the value is blank, so `name.present?` on the next line always equals `!name.nil?`. The guard can be collapsed to a single expression, consistent with the natural reading of the method.

```suggestion
    return display_name_override if display_name_override.present?
```

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds support for user-controlled display names by introducing profile settings UI and routing for display_name_override, then centralizing display-name precedence in User#display_name.

Changes:

  • Added display-name update route, controller params, settings props, and Svelte form.
  • Updated User#display_name to prefer display_name_override, with normalization and length validation.
  • Updated profile/OG display-name call sites and added model/controller tests.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
app/models/user.rb Adds display-name override precedence, normalization, and validation.
app/controllers/settings/profile_controller.rb Adds profile display-name update action and props.
app/controllers/settings/base_controller.rb Exposes display-name override and validation errors to settings pages.
app/javascript/pages/Users/Settings/Profile.svelte Adds the display-name settings form.
app/javascript/pages/Users/Settings/types.ts Adds display-name props/errors and subsection metadata.
config/routes.rb Adds the display-name settings PATCH route.
config/initializers/js_from_routes.rb Exports the new route to frontend path helpers.
app/controllers/profiles_controller.rb Uses centralized display_name for public profile payload/social text.
app/services/profile_og_image_generator.rb Uses centralized display_name for OG image generation.
test/models/user_test.rb Adds display-name precedence, normalization, and Slack sync coverage.
test/controllers/settings_profile_controller_test.rb Adds display-name update, clear, and validation controller coverage.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

const subsectionMap: Record<SectionId, SettingsSubsection[]> = {
profile: [
{ id: "user_region", label: "Region" },
{ id: "user_display_name", label: "Display name" },
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.

2 participants