Feature: Settings screen with account, theme, profile, reset + credits

Backend:
- New GET/PUT /api/me endpoint to read and update the authenticated
  user's profile (currently display_name). UserStore.UpdateDisplayName.
- Wired into the authed router.

App:
- New SettingsScreen + SettingsViewModel with five sections:
  * Account & Sync: login status, email, server URL, logout, connect.
  * Profile: edit display name (pushed to PUT /api/me when logged in).
  * Appearance: System / Light / Dark theme switch, persisted in
    SessionManager and applied via MitbringslTheme(sessionManager).
  * Data: 'Reset local data' wipes Room tables (server data kept).
  * About: version, 'Developed by Janik Dietz', and credits to
    GLM-5.2 + Gemini 3.6 Flash.
- Theme.kt now reads the user's theme preference (StateFlow) instead
  of only the system default; MainActivity passes SessionManager in.
- Navigation: new SettingsNavKey; settings gear icon in ListsScreen
  top bar; Settings links back to the Sync/Account screen.
- DTOs/API: UpdateMeRequestDto + getMe()/updateMe() for /api/me.
This commit is contained in:
Tronax 2026-08-06 10:39:12 +02:00
parent 3f187f1ede
commit 729865be78
Signed by: Tronax
SSH key fingerprint: SHA256:2pKKXDZucWvaF/GzXNz0FY53EAO1YDLN80bqS+TTz/o
13 changed files with 717 additions and 12 deletions

View file

@ -114,6 +114,27 @@ func (s *UserStore) GetByOIDCSubject(ctx context.Context, issuer, subject string
return u, nil
}
// UpdateDisplayName sets the display_name of the user with the given id.
// An empty displayName clears the field (stores NULL).
func (s *UserStore) UpdateDisplayName(ctx context.Context, id uuid.UUID, displayName string) (User, error) {
const q = `
UPDATE users SET display_name = NULLIF($2, ''), updated_at = now()
WHERE id = $1
RETURNING id, email, password_hash, oidc_subject, oidc_issuer, display_name`
var u User
var dn *string
err := s.pool.QueryRow(ctx, q, id, displayName).
Scan(&u.ID, &u.Email, &u.PasswordHash, &u.OIDCSubject, &u.OIDCIssuer, &dn)
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return User{}, ErrUserNotFound
}
return User{}, fmt.Errorf("update display name: %w", err)
}
u.DisplayName = dn
return u, nil
}
// CreateOIDCUser inserts a new user for an OIDC login. The user has no password
// (password_hash is NULL) and is identified by (issuer, subject). email may be
// empty if the IdP did not provide one; we store a synthesized placeholder so