feat: add theme_mode, theme_light, theme_dark to UserAppearanceSettings (#25076)

Part 1: Backend portion of a change broken into 2 PRs.
Part 2: #25077 

Adds three new UserAppearanceSettings fields (theme_mode, theme_light,
theme_dark) on top of the existing theme_preference and terminal_font.
Replaces GetUserThemePreference and GetUserTerminalFont with a single
GetUserAppearanceSettings aggregate query. The PUT handler is wrapped in
db.InTx so sync-mode's mode + slot writes can never half-apply.
This commit is contained in:
Jaayden Halko
2026-05-14 11:44:05 +07:00
committed by GitHub
parent d147dd3bdd
commit 024132e8a4
23 changed files with 1209 additions and 223 deletions
+122 -34
View File
@@ -25659,6 +25659,47 @@ func (q *sqlQuerier) GetUserAgentChatSendShortcut(ctx context.Context, userID uu
return agent_chat_send_shortcut, err
}
const getUserAppearanceSettings = `-- name: GetUserAppearanceSettings :one
SELECT
COALESCE(MAX(value) FILTER (WHERE key = 'theme_preference'), '')::text AS theme_preference,
COALESCE(MAX(value) FILTER (WHERE key = 'theme_mode'), '')::text AS theme_mode,
COALESCE(MAX(value) FILTER (WHERE key = 'theme_light'), '')::text AS theme_light,
COALESCE(MAX(value) FILTER (WHERE key = 'theme_dark'), '')::text AS theme_dark,
COALESCE(MAX(value) FILTER (WHERE key = 'terminal_font'), '')::text AS terminal_font
FROM
user_configs
WHERE
user_id = $1
AND key IN (
'theme_preference',
'theme_mode',
'theme_light',
'theme_dark',
'terminal_font'
)
`
type GetUserAppearanceSettingsRow struct {
ThemePreference string `db:"theme_preference" json:"theme_preference"`
ThemeMode string `db:"theme_mode" json:"theme_mode"`
ThemeLight string `db:"theme_light" json:"theme_light"`
ThemeDark string `db:"theme_dark" json:"theme_dark"`
TerminalFont string `db:"terminal_font" json:"terminal_font"`
}
func (q *sqlQuerier) GetUserAppearanceSettings(ctx context.Context, userID uuid.UUID) (GetUserAppearanceSettingsRow, error) {
row := q.db.QueryRowContext(ctx, getUserAppearanceSettings, userID)
var i GetUserAppearanceSettingsRow
err := row.Scan(
&i.ThemePreference,
&i.ThemeMode,
&i.ThemeLight,
&i.ThemeDark,
&i.TerminalFont,
)
return i, err
}
const getUserByEmailOrUsername = `-- name: GetUserByEmailOrUsername :one
SELECT
id, email, username, hashed_password, created_at, updated_at, status, rbac_roles, login_type, avatar_url, deleted, last_seen_at, quiet_hours_schedule, name, github_com_user_id, hashed_one_time_passcode, one_time_passcode_expires_at, is_system, is_service_account, chat_spend_limit_micros
@@ -25863,40 +25904,6 @@ func (q *sqlQuerier) GetUserTaskNotificationAlertDismissed(ctx context.Context,
return task_notification_alert_dismissed, err
}
const getUserTerminalFont = `-- name: GetUserTerminalFont :one
SELECT
value as terminal_font
FROM
user_configs
WHERE
user_id = $1
AND key = 'terminal_font'
`
func (q *sqlQuerier) GetUserTerminalFont(ctx context.Context, userID uuid.UUID) (string, error) {
row := q.db.QueryRowContext(ctx, getUserTerminalFont, userID)
var terminal_font string
err := row.Scan(&terminal_font)
return terminal_font, err
}
const getUserThemePreference = `-- name: GetUserThemePreference :one
SELECT
value as theme_preference
FROM
user_configs
WHERE
user_id = $1
AND key = 'theme_preference'
`
func (q *sqlQuerier) GetUserThemePreference(ctx context.Context, userID uuid.UUID) (string, error) {
row := q.db.QueryRowContext(ctx, getUserThemePreference, userID)
var theme_preference string
err := row.Scan(&theme_preference)
return theme_preference, err
}
const getUserThinkingDisplayMode = `-- name: GetUserThinkingDisplayMode :one
SELECT
value AS thinking_display_mode
@@ -26902,6 +26909,87 @@ func (q *sqlQuerier) UpdateUserTerminalFont(ctx context.Context, arg UpdateUserT
return i, err
}
const updateUserThemeDark = `-- name: UpdateUserThemeDark :one
INSERT INTO
user_configs (user_id, key, value)
VALUES
($1, 'theme_dark', $2)
ON CONFLICT
ON CONSTRAINT user_configs_pkey
DO UPDATE
SET
value = $2
WHERE user_configs.user_id = $1
AND user_configs.key = 'theme_dark'
RETURNING user_id, key, value
`
type UpdateUserThemeDarkParams struct {
UserID uuid.UUID `db:"user_id" json:"user_id"`
ThemeDark string `db:"theme_dark" json:"theme_dark"`
}
func (q *sqlQuerier) UpdateUserThemeDark(ctx context.Context, arg UpdateUserThemeDarkParams) (UserConfig, error) {
row := q.db.QueryRowContext(ctx, updateUserThemeDark, arg.UserID, arg.ThemeDark)
var i UserConfig
err := row.Scan(&i.UserID, &i.Key, &i.Value)
return i, err
}
const updateUserThemeLight = `-- name: UpdateUserThemeLight :one
INSERT INTO
user_configs (user_id, key, value)
VALUES
($1, 'theme_light', $2)
ON CONFLICT
ON CONSTRAINT user_configs_pkey
DO UPDATE
SET
value = $2
WHERE user_configs.user_id = $1
AND user_configs.key = 'theme_light'
RETURNING user_id, key, value
`
type UpdateUserThemeLightParams struct {
UserID uuid.UUID `db:"user_id" json:"user_id"`
ThemeLight string `db:"theme_light" json:"theme_light"`
}
func (q *sqlQuerier) UpdateUserThemeLight(ctx context.Context, arg UpdateUserThemeLightParams) (UserConfig, error) {
row := q.db.QueryRowContext(ctx, updateUserThemeLight, arg.UserID, arg.ThemeLight)
var i UserConfig
err := row.Scan(&i.UserID, &i.Key, &i.Value)
return i, err
}
const updateUserThemeMode = `-- name: UpdateUserThemeMode :one
INSERT INTO
user_configs (user_id, key, value)
VALUES
($1, 'theme_mode', $2)
ON CONFLICT
ON CONSTRAINT user_configs_pkey
DO UPDATE
SET
value = $2
WHERE user_configs.user_id = $1
AND user_configs.key = 'theme_mode'
RETURNING user_id, key, value
`
type UpdateUserThemeModeParams struct {
UserID uuid.UUID `db:"user_id" json:"user_id"`
ThemeMode string `db:"theme_mode" json:"theme_mode"`
}
func (q *sqlQuerier) UpdateUserThemeMode(ctx context.Context, arg UpdateUserThemeModeParams) (UserConfig, error) {
row := q.db.QueryRowContext(ctx, updateUserThemeMode, arg.UserID, arg.ThemeMode)
var i UserConfig
err := row.Scan(&i.UserID, &i.Key, &i.Value)
return i, err
}
const updateUserThemePreference = `-- name: UpdateUserThemePreference :one
INSERT INTO
user_configs (user_id, key, value)