mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add code diff display mode preference (#25027)
This commit is contained in:
+120
-51
@@ -1248,9 +1248,19 @@ func (api *API) userPreferenceSettings(rw http.ResponseWriter, r *http.Request)
|
||||
return
|
||||
}
|
||||
|
||||
codeDiffMode, err := api.Database.GetUserCodeDiffDisplayMode(ctx, user.ID)
|
||||
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Error reading user preference settings.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
httpapi.Write(ctx, rw, http.StatusOK, codersdk.UserPreferenceSettings{
|
||||
TaskNotificationAlertDismissed: taskAlertDismissed,
|
||||
ThinkingDisplayMode: sanitizeThinkingDisplayMode(thinkingMode),
|
||||
CodeDiffDisplayMode: sanitizeAgentDisplayMode(codeDiffMode),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1280,69 +1290,120 @@ func (api *API) putUserPreferenceSettings(rw http.ResponseWriter, r *http.Reques
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "Invalid thinking display mode.",
|
||||
Validations: []codersdk.ValidationError{
|
||||
{Field: "thinking_display_mode", Detail: "must be one of: auto, preview, always_expanded, always_collapsed"},
|
||||
{Field: "thinking_display_mode", Detail: thinkingDisplayModeValidationDetail},
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
var err error
|
||||
|
||||
var updatedTaskAlertDismissed bool
|
||||
if params.TaskNotificationAlertDismissed != nil {
|
||||
updatedTaskAlertDismissed, err = api.Database.UpdateUserTaskNotificationAlertDismissed(ctx, database.UpdateUserTaskNotificationAlertDismissedParams{
|
||||
UserID: user.ID,
|
||||
TaskNotificationAlertDismissed: *params.TaskNotificationAlertDismissed,
|
||||
if params.CodeDiffDisplayMode != "" &&
|
||||
!slices.Contains(codersdk.ValidAgentDisplayModes, params.CodeDiffDisplayMode) {
|
||||
httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{
|
||||
Message: "Invalid code diff display mode.",
|
||||
Validations: []codersdk.ValidationError{
|
||||
{Field: "code_diff_display_mode", Detail: agentDisplayModeValidationDetail},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error updating user task notification alert dismissed.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
} else {
|
||||
updatedTaskAlertDismissed, err = api.Database.GetUserTaskNotificationAlertDismissed(ctx, user.ID)
|
||||
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Error reading task notification alert dismissed.",
|
||||
Detail: err.Error(),
|
||||
return
|
||||
}
|
||||
var settings codersdk.UserPreferenceSettings
|
||||
err := api.Database.InTx(func(tx database.Store) error {
|
||||
var err error
|
||||
if params.TaskNotificationAlertDismissed != nil {
|
||||
settings.TaskNotificationAlertDismissed, err = tx.UpdateUserTaskNotificationAlertDismissed(ctx, database.UpdateUserTaskNotificationAlertDismissedParams{
|
||||
UserID: user.ID,
|
||||
TaskNotificationAlertDismissed: *params.TaskNotificationAlertDismissed,
|
||||
})
|
||||
if err != nil {
|
||||
return newUserPreferenceSettingsAPIError("Internal error updating user task notification alert dismissed.", err)
|
||||
}
|
||||
} else {
|
||||
settings.TaskNotificationAlertDismissed, err = tx.GetUserTaskNotificationAlertDismissed(ctx, user.ID)
|
||||
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||
return newUserPreferenceSettingsAPIError("Error reading task notification alert dismissed.", err)
|
||||
}
|
||||
}
|
||||
|
||||
if params.ThinkingDisplayMode != "" {
|
||||
updated, err := tx.UpdateUserThinkingDisplayMode(ctx, database.UpdateUserThinkingDisplayModeParams{
|
||||
UserID: user.ID,
|
||||
ThinkingDisplayMode: string(params.ThinkingDisplayMode),
|
||||
})
|
||||
if err != nil {
|
||||
return newUserPreferenceSettingsAPIError("Internal error updating thinking display mode.", err)
|
||||
}
|
||||
settings.ThinkingDisplayMode = sanitizeThinkingDisplayMode(updated)
|
||||
} else {
|
||||
stored, err := tx.GetUserThinkingDisplayMode(ctx, user.ID)
|
||||
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||
return newUserPreferenceSettingsAPIError("Error reading thinking display mode.", err)
|
||||
}
|
||||
settings.ThinkingDisplayMode = sanitizeThinkingDisplayMode(stored)
|
||||
}
|
||||
|
||||
if params.CodeDiffDisplayMode != "" {
|
||||
updated, err := tx.UpdateUserCodeDiffDisplayMode(ctx, database.UpdateUserCodeDiffDisplayModeParams{
|
||||
UserID: user.ID,
|
||||
CodeDiffDisplayMode: string(params.CodeDiffDisplayMode),
|
||||
})
|
||||
if err != nil {
|
||||
return newUserPreferenceSettingsAPIError("Internal error updating code diff display mode.", err)
|
||||
}
|
||||
settings.CodeDiffDisplayMode = sanitizeAgentDisplayMode(updated)
|
||||
} else {
|
||||
stored, err := tx.GetUserCodeDiffDisplayMode(ctx, user.ID)
|
||||
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||
return newUserPreferenceSettingsAPIError("Error reading code diff display mode.", err)
|
||||
}
|
||||
settings.CodeDiffDisplayMode = sanitizeAgentDisplayMode(stored)
|
||||
}
|
||||
return nil
|
||||
}, database.DefaultTXOptions().WithID("user_preference_settings"))
|
||||
if err != nil {
|
||||
var apiErr userPreferenceSettingsAPIError
|
||||
if errors.As(err, &apiErr) {
|
||||
httpapi.Write(ctx, rw, apiErr.statusCode, apiErr.response)
|
||||
return
|
||||
}
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error updating user preference settings.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
var resolvedThinkingMode codersdk.ThinkingDisplayMode
|
||||
if params.ThinkingDisplayMode != "" {
|
||||
updated, err := api.Database.UpdateUserThinkingDisplayMode(ctx, database.UpdateUserThinkingDisplayModeParams{
|
||||
UserID: user.ID,
|
||||
ThinkingDisplayMode: string(params.ThinkingDisplayMode),
|
||||
})
|
||||
if err != nil {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Internal error updating thinking display mode.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
resolvedThinkingMode = codersdk.ThinkingDisplayMode(updated)
|
||||
} else {
|
||||
stored, err := api.Database.GetUserThinkingDisplayMode(ctx, user.ID)
|
||||
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
|
||||
Message: "Error reading thinking display mode.",
|
||||
Detail: err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
resolvedThinkingMode = sanitizeThinkingDisplayMode(stored)
|
||||
}
|
||||
|
||||
httpapi.Write(ctx, rw, http.StatusOK, codersdk.UserPreferenceSettings{
|
||||
TaskNotificationAlertDismissed: updatedTaskAlertDismissed,
|
||||
ThinkingDisplayMode: resolvedThinkingMode,
|
||||
})
|
||||
httpapi.Write(ctx, rw, http.StatusOK, settings)
|
||||
}
|
||||
|
||||
type userPreferenceSettingsAPIError struct {
|
||||
statusCode int
|
||||
response codersdk.Response
|
||||
err error
|
||||
}
|
||||
|
||||
func newUserPreferenceSettingsAPIError(message string, err error) userPreferenceSettingsAPIError {
|
||||
return userPreferenceSettingsAPIError{
|
||||
statusCode: http.StatusInternalServerError,
|
||||
response: codersdk.Response{
|
||||
Message: message,
|
||||
Detail: err.Error(),
|
||||
},
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
|
||||
func (e userPreferenceSettingsAPIError) Error() string {
|
||||
return fmt.Sprintf("%s: %s", e.response.Message, e.err)
|
||||
}
|
||||
|
||||
func (e userPreferenceSettingsAPIError) Unwrap() error {
|
||||
return e.err
|
||||
}
|
||||
|
||||
const (
|
||||
thinkingDisplayModeValidationDetail = "must be one of: auto, preview, always_expanded, always_collapsed"
|
||||
agentDisplayModeValidationDetail = "must be one of: auto, always_expanded, always_collapsed"
|
||||
)
|
||||
|
||||
func sanitizeThinkingDisplayMode(raw string) codersdk.ThinkingDisplayMode {
|
||||
mode := codersdk.ThinkingDisplayMode(raw)
|
||||
if slices.Contains(codersdk.ValidThinkingDisplayModes, mode) {
|
||||
@@ -1351,6 +1412,14 @@ func sanitizeThinkingDisplayMode(raw string) codersdk.ThinkingDisplayMode {
|
||||
return codersdk.ThinkingDisplayModeAuto
|
||||
}
|
||||
|
||||
func sanitizeAgentDisplayMode(raw string) codersdk.AgentDisplayMode {
|
||||
mode := codersdk.AgentDisplayMode(raw)
|
||||
if slices.Contains(codersdk.ValidAgentDisplayModes, mode) {
|
||||
return mode
|
||||
}
|
||||
return codersdk.AgentDisplayModeAuto
|
||||
}
|
||||
|
||||
func isValidFontName(font codersdk.TerminalFontName) bool {
|
||||
return slices.Contains(codersdk.TerminalFontNames, font)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user