Files
Nitro-V3/CHANGELOG.md
T

4.7 KiB

Changelog

Badge System Rework (2026-04-04)

Bug Fixes

  • Slot 0 drag bug: Dragging from slot 0 no longer causes badges to disappear. The root cause was '0' being falsy in JavaScript, which made the drop handler take the wrong code path and overwrite the target badge.
  • Badge duplication: Fixed badges appearing in multiple slots when dragging in the InfoStand. The issue was a stale props fallback — after a drag operation, the hook updated correctly but the component fell back to old server props for empty slots, showing ghost copies.
  • Race condition: Replaced single boolean localChangeRef with a counter (pendingUpdatesRef) to correctly handle rapid sequential drag operations without the server overwriting local state.
  • Badge deduplication: toFixedSlots() now deduplicates badges, preventing the same badge from appearing in multiple slots even if the server returns duplicates.
  • Server badge dedup in InfoStand: RoomSessionUserBadgesEvent handler now deduplicates badges from the server before updating the avatar info.

Drag & Drop Visual Feedback

  • Custom drag preview: Badge image is used as the drag ghost instead of the browser default (via setDragImage).
  • Source opacity: The dragged item becomes semi-transparent (opacity-40) during drag.
  • Pulsing glow on drop targets: Valid drop targets pulse with a blue glow animation (animate-pulse-glow).
  • Drop settle animation: A brief scale-down animation (animate-drop-settle, 300ms) plays when a badge lands in a slot.
  • Remove indicator: Dragging an active badge over the inventory area shows a red pulsing background with a trash icon overlay.
  • Grab cursor: All draggable badge elements now show cursor-grab / cursor-grabbing.

Sparse Slot Support

  • activeBadgeCodes changed from compact string[] to fixed-size (string | null)[] array. Empty slots are null instead of being collapsed, allowing gaps between badges.
  • All operations (setBadgeAtSlot, removeBadge, reorderBadges, swapBadges, toggleBadge) work on the fixed-size array without compaction.

New Badge Glow (Feature)

  • Unseen (newly received) badges in the inventory now pulse with a gold glow (animate-pulse-glow-gold) instead of the previous flat green background.
  • The glow disappears when the badge is selected (unseen status cleared).

Badge Received Toast Notification (Feature)

  • When a new badge is received, a bubble notification appears with:
    • Badge image and localized name
    • "Indossa" / "Wear" button that directly equips the badge via toggleBadge and closes the notification
    • "Non ora" / "Later" link to dismiss
  • Auto-fades after 8 seconds (standard bubble behavior).
  • Uses the existing NotificationBubbleType.BADGE_RECEIVED (was defined but unused).
  • New component: NotificationBadgeReceivedBubbleView.

Dynamic Badge Slot Count

  • Badge slot count is now fully driven by user.badges.max.slots config (default: 5).
    • 5 slots: 5 badge slots + group badge in InfoStand (6 boxes total)
    • 6 slots: 6 badge slots, group badge is replaced by the 6th slot
  • Both the inventory grid and InfoStand layout adapt automatically.
  • Removed all hardcoded maxSlots = 5 references.

InfoStand Double-Click to Remove

  • Double-clicking a badge in the InfoStand removes it from active badges (own user only).

Localization

  • Added notification.badge.received key:
    • IT: "Nuovo Distintivo!"
    • EN: "New Badge!"
  • Located in public/nitro-assets/config/UITexts.json and UITexts_en.json.

Files Modified

File Changes
src/hooks/inventory/useInventoryBadges.ts Sparse slots, dedup, race condition fix, toFixedSlots
src/hooks/notification/useNotification.ts BadgeReceivedEvent listener
src/components/inventory/views/badge/InventoryBadgeView.tsx Visual feedback, dynamic maxSlots, fix '0' falsy
src/components/inventory/views/badge/InventoryBadgeItemView.tsx Drag preview, opacity, cursor
src/components/room/widgets/avatar-info/infostand/InfoStandBadgeSlotView.tsx Visual feedback, double-click remove, no stale props
src/components/room/widgets/avatar-info/infostand/InfoStandWidgetUserView.tsx Dynamic layout, server badge dedup
src/components/notification-center/views/bubble-layouts/GetBubbleLayout.tsx BADGE_RECEIVED routing
src/components/notification-center/views/bubble-layouts/NotificationBadgeReceivedBubbleView.tsx New component
src/layout/InfiniteGrid.tsx Gold glow for unseen items
tailwind.config.js Custom keyframes and animations

Configuration

{
  "user.badges.max.slots": 5
}

Set to 6 to replace the group badge slot with a 6th badge slot.