You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
679 lines
19 KiB
Go
679 lines
19 KiB
Go
package valueobjects
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"knowfoolery/backend/shared/types"
|
|
"knowfoolery/backend/shared/errors"
|
|
)
|
|
|
|
// UserPreferences represents a user's preferences and settings
|
|
type UserPreferences struct {
|
|
// Game preferences
|
|
preferredDifficulty types.DifficultyLevel
|
|
preferredThemes []types.ThemeID
|
|
enableHints bool
|
|
enableTimer bool
|
|
enableSound bool
|
|
enableNotifications bool
|
|
|
|
// Display preferences
|
|
theme string // "light", "dark", "auto"
|
|
language string // ISO 639-1 language code
|
|
timezone string // IANA timezone
|
|
|
|
// Privacy preferences
|
|
showProfile bool
|
|
showStatistics bool
|
|
showLeaderboard bool
|
|
allowFriendRequests bool
|
|
|
|
// Notification preferences
|
|
emailNotifications *EmailNotificationSettings
|
|
pushNotifications *PushNotificationSettings
|
|
|
|
// Accessibility preferences
|
|
accessibility *AccessibilitySettings
|
|
|
|
// Update tracking
|
|
updatedAt types.Timestamp
|
|
}
|
|
|
|
// EmailNotificationSettings represents email notification preferences
|
|
type EmailNotificationSettings struct {
|
|
Enabled bool `json:"enabled"`
|
|
GameInvitations bool `json:"game_invitations"`
|
|
LeaderboardUpdates bool `json:"leaderboard_updates"`
|
|
WeeklyDigest bool `json:"weekly_digest"`
|
|
SecurityAlerts bool `json:"security_alerts"`
|
|
ProductUpdates bool `json:"product_updates"`
|
|
}
|
|
|
|
// PushNotificationSettings represents push notification preferences
|
|
type PushNotificationSettings struct {
|
|
Enabled bool `json:"enabled"`
|
|
GameInvitations bool `json:"game_invitations"`
|
|
TurnReminders bool `json:"turn_reminders"`
|
|
LeaderboardUpdates bool `json:"leaderboard_updates"`
|
|
DailyReminders bool `json:"daily_reminders"`
|
|
}
|
|
|
|
// AccessibilitySettings represents accessibility preferences
|
|
type AccessibilitySettings struct {
|
|
HighContrast bool `json:"high_contrast"`
|
|
LargeText bool `json:"large_text"`
|
|
ReducedMotion bool `json:"reduced_motion"`
|
|
ScreenReaderSupport bool `json:"screen_reader_support"`
|
|
KeyboardNavigation bool `json:"keyboard_navigation"`
|
|
FontSize float64 `json:"font_size"` // 0.8 - 2.0 multiplier
|
|
}
|
|
|
|
// NewDefaultUserPreferences creates default user preferences
|
|
func NewDefaultUserPreferences() *UserPreferences {
|
|
return &UserPreferences{
|
|
preferredDifficulty: types.DifficultyMedium,
|
|
preferredThemes: []types.ThemeID{},
|
|
enableHints: true,
|
|
enableTimer: true,
|
|
enableSound: true,
|
|
enableNotifications: true,
|
|
theme: "auto",
|
|
language: "en",
|
|
timezone: "UTC",
|
|
showProfile: true,
|
|
showStatistics: true,
|
|
showLeaderboard: true,
|
|
allowFriendRequests: true,
|
|
emailNotifications: &EmailNotificationSettings{
|
|
Enabled: true,
|
|
GameInvitations: true,
|
|
LeaderboardUpdates: false,
|
|
WeeklyDigest: true,
|
|
SecurityAlerts: true,
|
|
ProductUpdates: false,
|
|
},
|
|
pushNotifications: &PushNotificationSettings{
|
|
Enabled: true,
|
|
GameInvitations: true,
|
|
TurnReminders: true,
|
|
LeaderboardUpdates: false,
|
|
DailyReminders: false,
|
|
},
|
|
accessibility: &AccessibilitySettings{
|
|
HighContrast: false,
|
|
LargeText: false,
|
|
ReducedMotion: false,
|
|
ScreenReaderSupport: false,
|
|
KeyboardNavigation: false,
|
|
FontSize: 1.0,
|
|
},
|
|
updatedAt: types.NewTimestamp(),
|
|
}
|
|
}
|
|
|
|
// NewUserPreferences creates user preferences with specified values
|
|
func NewUserPreferences(
|
|
preferredDifficulty types.DifficultyLevel,
|
|
preferredThemes []types.ThemeID,
|
|
enableHints bool,
|
|
enableTimer bool,
|
|
) (*UserPreferences, error) {
|
|
preferences := NewDefaultUserPreferences()
|
|
|
|
// Validate and set preferred difficulty
|
|
if err := preferences.SetPreferredDifficulty(preferredDifficulty); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Set preferred themes
|
|
if err := preferences.SetPreferredThemes(preferredThemes); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
preferences.enableHints = enableHints
|
|
preferences.enableTimer = enableTimer
|
|
|
|
return preferences, nil
|
|
}
|
|
|
|
// Getters
|
|
|
|
// PreferredDifficulty returns the preferred difficulty level
|
|
func (p *UserPreferences) PreferredDifficulty() types.DifficultyLevel {
|
|
return p.preferredDifficulty
|
|
}
|
|
|
|
// PreferredThemes returns the preferred themes
|
|
func (p *UserPreferences) PreferredThemes() []types.ThemeID {
|
|
return append([]types.ThemeID(nil), p.preferredThemes...) // Return copy
|
|
}
|
|
|
|
// EnableHints returns true if hints are enabled
|
|
func (p *UserPreferences) EnableHints() bool {
|
|
return p.enableHints
|
|
}
|
|
|
|
// EnableTimer returns true if timer is enabled
|
|
func (p *UserPreferences) EnableTimer() bool {
|
|
return p.enableTimer
|
|
}
|
|
|
|
// EnableSound returns true if sound is enabled
|
|
func (p *UserPreferences) EnableSound() bool {
|
|
return p.enableSound
|
|
}
|
|
|
|
// EnableNotifications returns true if notifications are enabled
|
|
func (p *UserPreferences) EnableNotifications() bool {
|
|
return p.enableNotifications
|
|
}
|
|
|
|
// Theme returns the display theme
|
|
func (p *UserPreferences) Theme() string {
|
|
return p.theme
|
|
}
|
|
|
|
// Language returns the language code
|
|
func (p *UserPreferences) Language() string {
|
|
return p.language
|
|
}
|
|
|
|
// Timezone returns the timezone
|
|
func (p *UserPreferences) Timezone() string {
|
|
return p.timezone
|
|
}
|
|
|
|
// ShowProfile returns true if profile should be shown
|
|
func (p *UserPreferences) ShowProfile() bool {
|
|
return p.showProfile
|
|
}
|
|
|
|
// ShowStatistics returns true if statistics should be shown
|
|
func (p *UserPreferences) ShowStatistics() bool {
|
|
return p.showStatistics
|
|
}
|
|
|
|
// ShowLeaderboard returns true if leaderboard should be shown
|
|
func (p *UserPreferences) ShowLeaderboard() bool {
|
|
return p.showLeaderboard
|
|
}
|
|
|
|
// AllowFriendRequests returns true if friend requests are allowed
|
|
func (p *UserPreferences) AllowFriendRequests() bool {
|
|
return p.allowFriendRequests
|
|
}
|
|
|
|
// EmailNotifications returns email notification settings
|
|
func (p *UserPreferences) EmailNotifications() *EmailNotificationSettings {
|
|
if p.emailNotifications == nil {
|
|
return nil
|
|
}
|
|
// Return copy
|
|
return &EmailNotificationSettings{
|
|
Enabled: p.emailNotifications.Enabled,
|
|
GameInvitations: p.emailNotifications.GameInvitations,
|
|
LeaderboardUpdates: p.emailNotifications.LeaderboardUpdates,
|
|
WeeklyDigest: p.emailNotifications.WeeklyDigest,
|
|
SecurityAlerts: p.emailNotifications.SecurityAlerts,
|
|
ProductUpdates: p.emailNotifications.ProductUpdates,
|
|
}
|
|
}
|
|
|
|
// PushNotifications returns push notification settings
|
|
func (p *UserPreferences) PushNotifications() *PushNotificationSettings {
|
|
if p.pushNotifications == nil {
|
|
return nil
|
|
}
|
|
// Return copy
|
|
return &PushNotificationSettings{
|
|
Enabled: p.pushNotifications.Enabled,
|
|
GameInvitations: p.pushNotifications.GameInvitations,
|
|
TurnReminders: p.pushNotifications.TurnReminders,
|
|
LeaderboardUpdates: p.pushNotifications.LeaderboardUpdates,
|
|
DailyReminders: p.pushNotifications.DailyReminders,
|
|
}
|
|
}
|
|
|
|
// Accessibility returns accessibility settings
|
|
func (p *UserPreferences) Accessibility() *AccessibilitySettings {
|
|
if p.accessibility == nil {
|
|
return nil
|
|
}
|
|
// Return copy
|
|
return &AccessibilitySettings{
|
|
HighContrast: p.accessibility.HighContrast,
|
|
LargeText: p.accessibility.LargeText,
|
|
ReducedMotion: p.accessibility.ReducedMotion,
|
|
ScreenReaderSupport: p.accessibility.ScreenReaderSupport,
|
|
KeyboardNavigation: p.accessibility.KeyboardNavigation,
|
|
FontSize: p.accessibility.FontSize,
|
|
}
|
|
}
|
|
|
|
// UpdatedAt returns the last update timestamp
|
|
func (p *UserPreferences) UpdatedAt() types.Timestamp {
|
|
return p.updatedAt
|
|
}
|
|
|
|
// Business methods
|
|
|
|
// SetPreferredDifficulty sets the preferred difficulty level
|
|
func (p *UserPreferences) SetPreferredDifficulty(difficulty types.DifficultyLevel) error {
|
|
// Validate difficulty level
|
|
validDifficulties := []types.DifficultyLevel{
|
|
types.DifficultyEasy,
|
|
types.DifficultyMedium,
|
|
types.DifficultyHard,
|
|
types.DifficultyExpert,
|
|
types.DifficultyImpossible,
|
|
}
|
|
|
|
isValid := false
|
|
for _, valid := range validDifficulties {
|
|
if difficulty == valid {
|
|
isValid = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !isValid {
|
|
return errors.ErrValidationFailed("preferred_difficulty", "invalid difficulty level")
|
|
}
|
|
|
|
p.preferredDifficulty = difficulty
|
|
p.markUpdated()
|
|
|
|
return nil
|
|
}
|
|
|
|
// SetPreferredThemes sets the preferred themes
|
|
func (p *UserPreferences) SetPreferredThemes(themes []types.ThemeID) error {
|
|
if len(themes) > types.MaxPreferredThemes {
|
|
return errors.ErrValidationFailed("preferred_themes",
|
|
fmt.Sprintf("too many preferred themes (max %d)", types.MaxPreferredThemes))
|
|
}
|
|
|
|
// Validate theme IDs
|
|
for i, themeID := range themes {
|
|
if themeID.IsEmpty() {
|
|
return errors.ErrValidationFailed("preferred_themes",
|
|
fmt.Sprintf("theme ID at index %d is empty", i))
|
|
}
|
|
}
|
|
|
|
// Remove duplicates
|
|
uniqueThemes := make([]types.ThemeID, 0, len(themes))
|
|
themeSet := make(map[types.ThemeID]bool)
|
|
|
|
for _, themeID := range themes {
|
|
if !themeSet[themeID] {
|
|
uniqueThemes = append(uniqueThemes, themeID)
|
|
themeSet[themeID] = true
|
|
}
|
|
}
|
|
|
|
p.preferredThemes = uniqueThemes
|
|
p.markUpdated()
|
|
|
|
return nil
|
|
}
|
|
|
|
// AddPreferredTheme adds a theme to preferred themes
|
|
func (p *UserPreferences) AddPreferredTheme(themeID types.ThemeID) error {
|
|
if themeID.IsEmpty() {
|
|
return errors.ErrValidationFailed("theme_id", "theme ID cannot be empty")
|
|
}
|
|
|
|
// Check if already in preferred themes
|
|
for _, existing := range p.preferredThemes {
|
|
if existing == themeID {
|
|
return nil // Already exists
|
|
}
|
|
}
|
|
|
|
if len(p.preferredThemes) >= types.MaxPreferredThemes {
|
|
return errors.ErrValidationFailed("preferred_themes",
|
|
fmt.Sprintf("too many preferred themes (max %d)", types.MaxPreferredThemes))
|
|
}
|
|
|
|
p.preferredThemes = append(p.preferredThemes, themeID)
|
|
p.markUpdated()
|
|
|
|
return nil
|
|
}
|
|
|
|
// RemovePreferredTheme removes a theme from preferred themes
|
|
func (p *UserPreferences) RemovePreferredTheme(themeID types.ThemeID) error {
|
|
for i, existing := range p.preferredThemes {
|
|
if existing == themeID {
|
|
p.preferredThemes = append(p.preferredThemes[:i], p.preferredThemes[i+1:]...)
|
|
p.markUpdated()
|
|
return nil
|
|
}
|
|
}
|
|
|
|
return errors.ErrNotFound("preferred_theme", string(themeID))
|
|
}
|
|
|
|
// SetGamePreferences sets game-related preferences
|
|
func (p *UserPreferences) SetGamePreferences(
|
|
enableHints bool,
|
|
enableTimer bool,
|
|
enableSound bool,
|
|
enableNotifications bool,
|
|
) {
|
|
p.enableHints = enableHints
|
|
p.enableTimer = enableTimer
|
|
p.enableSound = enableSound
|
|
p.enableNotifications = enableNotifications
|
|
p.markUpdated()
|
|
}
|
|
|
|
// SetDisplayPreferences sets display-related preferences
|
|
func (p *UserPreferences) SetDisplayPreferences(
|
|
theme string,
|
|
language string,
|
|
timezone string,
|
|
) error {
|
|
if err := p.SetTheme(theme); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := p.SetLanguage(language); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := p.SetTimezone(timezone); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// SetTheme sets the display theme
|
|
func (p *UserPreferences) SetTheme(theme string) error {
|
|
validThemes := []string{"light", "dark", "auto"}
|
|
|
|
isValid := false
|
|
for _, valid := range validThemes {
|
|
if theme == valid {
|
|
isValid = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !isValid {
|
|
return errors.ErrValidationFailed("theme", "theme must be 'light', 'dark', or 'auto'")
|
|
}
|
|
|
|
p.theme = theme
|
|
p.markUpdated()
|
|
|
|
return nil
|
|
}
|
|
|
|
// SetLanguage sets the language
|
|
func (p *UserPreferences) SetLanguage(language string) error {
|
|
if len(language) != 2 {
|
|
return errors.ErrValidationFailed("language", "language must be a 2-character ISO 639-1 code")
|
|
}
|
|
|
|
// Could validate against known language codes
|
|
p.language = language
|
|
p.markUpdated()
|
|
|
|
return nil
|
|
}
|
|
|
|
// SetTimezone sets the timezone
|
|
func (p *UserPreferences) SetTimezone(timezone string) error {
|
|
// Basic validation - could be more comprehensive
|
|
if timezone == "" {
|
|
timezone = "UTC"
|
|
}
|
|
|
|
p.timezone = timezone
|
|
p.markUpdated()
|
|
|
|
return nil
|
|
}
|
|
|
|
// SetPrivacyPreferences sets privacy-related preferences
|
|
func (p *UserPreferences) SetPrivacyPreferences(
|
|
showProfile bool,
|
|
showStatistics bool,
|
|
showLeaderboard bool,
|
|
allowFriendRequests bool,
|
|
) {
|
|
p.showProfile = showProfile
|
|
p.showStatistics = showStatistics
|
|
p.showLeaderboard = showLeaderboard
|
|
p.allowFriendRequests = allowFriendRequests
|
|
p.markUpdated()
|
|
}
|
|
|
|
// UpdateEmailNotifications updates email notification settings
|
|
func (p *UserPreferences) UpdateEmailNotifications(settings *EmailNotificationSettings) error {
|
|
if settings == nil {
|
|
return errors.ErrValidationFailed("email_notifications", "email notification settings cannot be nil")
|
|
}
|
|
|
|
p.emailNotifications = &EmailNotificationSettings{
|
|
Enabled: settings.Enabled,
|
|
GameInvitations: settings.GameInvitations,
|
|
LeaderboardUpdates: settings.LeaderboardUpdates,
|
|
WeeklyDigest: settings.WeeklyDigest,
|
|
SecurityAlerts: settings.SecurityAlerts,
|
|
ProductUpdates: settings.ProductUpdates,
|
|
}
|
|
p.markUpdated()
|
|
|
|
return nil
|
|
}
|
|
|
|
// UpdatePushNotifications updates push notification settings
|
|
func (p *UserPreferences) UpdatePushNotifications(settings *PushNotificationSettings) error {
|
|
if settings == nil {
|
|
return errors.ErrValidationFailed("push_notifications", "push notification settings cannot be nil")
|
|
}
|
|
|
|
p.pushNotifications = &PushNotificationSettings{
|
|
Enabled: settings.Enabled,
|
|
GameInvitations: settings.GameInvitations,
|
|
TurnReminders: settings.TurnReminders,
|
|
LeaderboardUpdates: settings.LeaderboardUpdates,
|
|
DailyReminders: settings.DailyReminders,
|
|
}
|
|
p.markUpdated()
|
|
|
|
return nil
|
|
}
|
|
|
|
// UpdateAccessibility updates accessibility settings
|
|
func (p *UserPreferences) UpdateAccessibility(settings *AccessibilitySettings) error {
|
|
if settings == nil {
|
|
return errors.ErrValidationFailed("accessibility", "accessibility settings cannot be nil")
|
|
}
|
|
|
|
// Validate font size
|
|
if settings.FontSize < 0.5 || settings.FontSize > 3.0 {
|
|
return errors.ErrValidationFailed("font_size", "font size must be between 0.5 and 3.0")
|
|
}
|
|
|
|
p.accessibility = &AccessibilitySettings{
|
|
HighContrast: settings.HighContrast,
|
|
LargeText: settings.LargeText,
|
|
ReducedMotion: settings.ReducedMotion,
|
|
ScreenReaderSupport: settings.ScreenReaderSupport,
|
|
KeyboardNavigation: settings.KeyboardNavigation,
|
|
FontSize: settings.FontSize,
|
|
}
|
|
p.markUpdated()
|
|
|
|
return nil
|
|
}
|
|
|
|
// Query methods
|
|
|
|
// HasPreferredTheme checks if a theme is in preferred themes
|
|
func (p *UserPreferences) HasPreferredTheme(themeID types.ThemeID) bool {
|
|
for _, preferred := range p.preferredThemes {
|
|
if preferred == themeID {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// IsAccessibilityEnabled returns true if any accessibility features are enabled
|
|
func (p *UserPreferences) IsAccessibilityEnabled() bool {
|
|
if p.accessibility == nil {
|
|
return false
|
|
}
|
|
|
|
return p.accessibility.HighContrast ||
|
|
p.accessibility.LargeText ||
|
|
p.accessibility.ReducedMotion ||
|
|
p.accessibility.ScreenReaderSupport ||
|
|
p.accessibility.KeyboardNavigation ||
|
|
p.accessibility.FontSize != 1.0
|
|
}
|
|
|
|
// AreEmailNotificationsEnabled returns true if email notifications are globally enabled
|
|
func (p *UserPreferences) AreEmailNotificationsEnabled() bool {
|
|
return p.emailNotifications != nil && p.emailNotifications.Enabled
|
|
}
|
|
|
|
// ArePushNotificationsEnabled returns true if push notifications are globally enabled
|
|
func (p *UserPreferences) ArePushNotificationsEnabled() bool {
|
|
return p.pushNotifications != nil && p.pushNotifications.Enabled
|
|
}
|
|
|
|
// Validation
|
|
|
|
// Validate performs comprehensive validation
|
|
func (p *UserPreferences) Validate() *types.ValidationResult {
|
|
result := types.NewValidationResult()
|
|
|
|
// Validate preferred difficulty
|
|
validDifficulties := []types.DifficultyLevel{
|
|
types.DifficultyEasy,
|
|
types.DifficultyMedium,
|
|
types.DifficultyHard,
|
|
types.DifficultyExpert,
|
|
types.DifficultyImpossible,
|
|
}
|
|
|
|
isValidDifficulty := false
|
|
for _, valid := range validDifficulties {
|
|
if p.preferredDifficulty == valid {
|
|
isValidDifficulty = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !isValidDifficulty {
|
|
result.AddError("invalid preferred difficulty")
|
|
}
|
|
|
|
// Validate preferred themes count
|
|
if len(p.preferredThemes) > types.MaxPreferredThemes {
|
|
result.AddErrorf("too many preferred themes (max %d)", types.MaxPreferredThemes)
|
|
}
|
|
|
|
// Validate theme IDs
|
|
for i, themeID := range p.preferredThemes {
|
|
if themeID.IsEmpty() {
|
|
result.AddErrorf("preferred theme at index %d is empty", i)
|
|
}
|
|
}
|
|
|
|
// Validate theme
|
|
validThemes := []string{"light", "dark", "auto"}
|
|
isValidTheme := false
|
|
for _, valid := range validThemes {
|
|
if p.theme == valid {
|
|
isValidTheme = true
|
|
break
|
|
}
|
|
}
|
|
|
|
if !isValidTheme {
|
|
result.AddError("invalid theme")
|
|
}
|
|
|
|
// Validate language
|
|
if len(p.language) != 2 {
|
|
result.AddError("invalid language code")
|
|
}
|
|
|
|
// Validate accessibility settings
|
|
if p.accessibility != nil {
|
|
if p.accessibility.FontSize < 0.5 || p.accessibility.FontSize > 3.0 {
|
|
result.AddError("font size must be between 0.5 and 3.0")
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// Helper methods
|
|
|
|
// markUpdated updates the timestamp
|
|
func (p *UserPreferences) markUpdated() {
|
|
p.updatedAt = types.NewTimestamp()
|
|
}
|
|
|
|
// ToSnapshot creates a read-only snapshot
|
|
func (p *UserPreferences) ToSnapshot() *UserPreferencesSnapshot {
|
|
return &UserPreferencesSnapshot{
|
|
PreferredDifficulty: p.preferredDifficulty,
|
|
PreferredThemes: append([]types.ThemeID(nil), p.preferredThemes...),
|
|
EnableHints: p.enableHints,
|
|
EnableTimer: p.enableTimer,
|
|
EnableSound: p.enableSound,
|
|
EnableNotifications: p.enableNotifications,
|
|
Theme: p.theme,
|
|
Language: p.language,
|
|
Timezone: p.timezone,
|
|
ShowProfile: p.showProfile,
|
|
ShowStatistics: p.showStatistics,
|
|
ShowLeaderboard: p.showLeaderboard,
|
|
AllowFriendRequests: p.allowFriendRequests,
|
|
EmailNotifications: p.EmailNotifications(),
|
|
PushNotifications: p.PushNotifications(),
|
|
Accessibility: p.Accessibility(),
|
|
UpdatedAt: p.updatedAt,
|
|
}
|
|
}
|
|
|
|
// UserPreferencesSnapshot represents a read-only view of user preferences
|
|
type UserPreferencesSnapshot struct {
|
|
PreferredDifficulty types.DifficultyLevel `json:"preferred_difficulty"`
|
|
PreferredThemes []types.ThemeID `json:"preferred_themes"`
|
|
EnableHints bool `json:"enable_hints"`
|
|
EnableTimer bool `json:"enable_timer"`
|
|
EnableSound bool `json:"enable_sound"`
|
|
EnableNotifications bool `json:"enable_notifications"`
|
|
Theme string `json:"theme"`
|
|
Language string `json:"language"`
|
|
Timezone string `json:"timezone"`
|
|
ShowProfile bool `json:"show_profile"`
|
|
ShowStatistics bool `json:"show_statistics"`
|
|
ShowLeaderboard bool `json:"show_leaderboard"`
|
|
AllowFriendRequests bool `json:"allow_friend_requests"`
|
|
EmailNotifications *EmailNotificationSettings `json:"email_notifications"`
|
|
PushNotifications *PushNotificationSettings `json:"push_notifications"`
|
|
Accessibility *AccessibilitySettings `json:"accessibility"`
|
|
UpdatedAt types.Timestamp `json:"updated_at"`
|
|
}
|
|
|
|
// HasPreferredTheme checks if a theme is preferred in the snapshot
|
|
func (ps *UserPreferencesSnapshot) HasPreferredTheme(themeID types.ThemeID) bool {
|
|
for _, preferred := range ps.PreferredThemes {
|
|
if preferred == themeID {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
} |