feat(cosmetics): оформление профиля — галерея, роли и личные стили
- миграция 00013: guild_cosmetics (рамки и иконки) и user_styles («для друзей» и пер-серверные стили) (AGENT.md 7.2, 7.4) - store: CRUD галереи, личные стили и вычисление оформления поэлементно (роль → пер-серверный стиль → «для друзей» → дефолт) с откатом, когда роль больше не выдаёт элемент - API: галерея сервера под MANAGE_ROLES, оформление роли в create/update, GET/PUT/DELETE /users/@me/styles с доступными элементами по областям - клиент: редактор личного стиля с предпросмотром, галерея оформления в настройках сервера, оформление роли в разделе «Роли» - рендер: рамка под аватаром, иконка рядом с ником, цвет и встроенные эффекты ника (CSS, при reduced-motion статично) в ленте и списке участников
This commit is contained in:
@@ -36,6 +36,11 @@ type profilePayload struct {
|
||||
Timezone string `json:"timezone"`
|
||||
// LastSeenAt — когда пользователя видели последний раз (для друзей).
|
||||
LastSeenAt string `json:"last_seen_at,omitempty"`
|
||||
// CreatedAt — дата регистрации: показывается в чужом профиле (AGENT.md 7.2).
|
||||
CreatedAt string `json:"created_at,omitempty"`
|
||||
// Cosmetics — оформление «для друзей»: применяется в DM, друзьях и
|
||||
// глобальных местах (AGENT.md 7.2).
|
||||
Cosmetics *cosmeticsPayload `json:"cosmetics,omitempty"`
|
||||
}
|
||||
|
||||
// profileFromUser собирает профиль; состояние 2FA читается из сервиса
|
||||
@@ -81,6 +86,9 @@ func profileFromUser(user *store.User, includePrivate bool) profilePayload {
|
||||
if user.LastSeenAt != nil {
|
||||
payload.LastSeenAt = user.LastSeenAt.UTC().Format(time.RFC3339)
|
||||
}
|
||||
if !user.CreatedAt.IsZero() {
|
||||
payload.CreatedAt = user.CreatedAt.UTC().Format(time.RFC3339)
|
||||
}
|
||||
return payload
|
||||
}
|
||||
|
||||
@@ -359,6 +367,10 @@ func (s *Server) registerUserRoutes(api huma.API) {
|
||||
}
|
||||
output := &userOutput{}
|
||||
output.Body.User = s.profileFromUser(ctx, user, false)
|
||||
// Оформление «для друзей»: в чужом профиле видно глобальный стиль (7.2).
|
||||
if cosmetics, err := s.store.EffectiveCosmeticsForUser(ctx, user.ID); err == nil {
|
||||
output.Body.User.Cosmetics = cosmeticsFromEffective(cosmetics)
|
||||
}
|
||||
return output, nil
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user