ultisuite-backend/internal/api/mail/settings.go
2026-05-24 00:03:36 +02:00

143 lines
4.0 KiB
Go

package mail
import (
"context"
"encoding/json"
"strings"
"github.com/jackc/pgx/v5"
)
func (s *Service) GetMailSettings(ctx context.Context, externalID string) (MailSettings, error) {
defaults := defaultMailSettings()
var density, themeMode, backgroundID, inboxSort, readingPane *string
var conversationMode *bool
var notificationsJSON []byte
var updatedAt any
err := s.db.QueryRow(ctx, `
SELECT
s.preferences->'mail'->>'density',
s.preferences->'mail'->>'theme_mode',
s.preferences->'mail'->>'background_id',
s.preferences->'mail'->>'inbox_sort',
s.preferences->'mail'->>'reading_pane',
(s.preferences->'mail'->>'conversation_mode')::boolean,
s.preferences->'mail'->'notifications',
s.updated_at
FROM users u
LEFT JOIN settings s ON s.user_id = u.id
WHERE u.external_id = $1
`, externalID).Scan(&density, &themeMode, &backgroundID, &inboxSort, &readingPane, &conversationMode, &notificationsJSON, &updatedAt)
if err != nil {
if err == pgx.ErrNoRows {
return defaults, nil
}
return MailSettings{}, err
}
if density != nil && *density != "" {
defaults.Density = *density
}
if themeMode != nil && *themeMode != "" {
defaults.ThemeMode = *themeMode
}
if backgroundID != nil && *backgroundID != "" {
defaults.BackgroundID = *backgroundID
}
if inboxSort != nil && *inboxSort != "" {
defaults.InboxSort = *inboxSort
}
if readingPane != nil && *readingPane != "" {
defaults.ReadingPane = *readingPane
}
if conversationMode != nil {
defaults.ConversationMode = *conversationMode
}
if len(notificationsJSON) > 0 && string(notificationsJSON) != "null" {
var n MailNotificationSettings
if err := json.Unmarshal(notificationsJSON, &n); err == nil {
defaults.Notifications = n
}
}
if updatedAt != nil {
defaults.UpdatedAt = updatedAt
}
return defaults, nil
}
func (s *Service) UpdateMailSettings(ctx context.Context, externalID string, req *patchMailSettingsRequest) (MailSettings, error) {
patch := map[string]any{}
if req.Density != nil {
patch["density"] = strings.ToLower(strings.TrimSpace(*req.Density))
}
if req.ThemeMode != nil {
patch["theme_mode"] = strings.ToLower(strings.TrimSpace(*req.ThemeMode))
}
if req.BackgroundID != nil {
patch["background_id"] = strings.ToLower(strings.TrimSpace(*req.BackgroundID))
}
if req.InboxSort != nil {
patch["inbox_sort"] = strings.ToLower(strings.TrimSpace(*req.InboxSort))
}
if req.ReadingPane != nil {
patch["reading_pane"] = strings.ToLower(strings.TrimSpace(*req.ReadingPane))
}
if req.ConversationMode != nil {
patch["conversation_mode"] = *req.ConversationMode
}
if req.Notifications != nil {
current, err := s.GetMailSettings(ctx, externalID)
if err != nil {
return MailSettings{}, err
}
merged := current.Notifications
if req.Notifications.DesktopNewMail != nil {
merged.DesktopNewMail = *req.Notifications.DesktopNewMail
}
if req.Notifications.DesktopMentions != nil {
merged.DesktopMentions = *req.Notifications.DesktopMentions
}
if req.Notifications.EmailDigest != nil {
merged.EmailDigest = *req.Notifications.EmailDigest
}
if req.Notifications.SoundEnabled != nil {
merged.SoundEnabled = *req.Notifications.SoundEnabled
}
patch["notifications"] = merged
}
patchJSON, err := json.Marshal(patch)
if err != nil {
return MailSettings{}, err
}
var updatedAt any
err = s.db.QueryRow(ctx, `
INSERT INTO settings (user_id, preferences)
VALUES (
(SELECT id FROM users WHERE external_id = $1),
jsonb_build_object('mail', $2::jsonb)
)
ON CONFLICT (user_id) DO UPDATE SET
preferences = jsonb_set(
COALESCE(settings.preferences, '{}'::jsonb),
'{mail}',
COALESCE(settings.preferences->'mail', '{}'::jsonb) || $2::jsonb
),
updated_at = NOW()
RETURNING updated_at
`, externalID, patchJSON).Scan(&updatedAt)
if err != nil {
return MailSettings{}, err
}
result, err := s.GetMailSettings(ctx, externalID)
if err != nil {
return MailSettings{}, err
}
result.UpdatedAt = updatedAt
return result, nil
}