Conversation
|
@MadakiElisha is attempting to deploy a commit to the olufunbiik's projects Team on Vercel. A member of the Team first needs to authorize it. |
📝 WalkthroughWalkthroughThis PR implements tip batching in the live performance overlay to stabilize rapid updates, applies React.memo optimization to reduce unnecessary re-renders, extends the LeaderboardEntry type with stability fields, adds accessibility attributes, and re-enables comprehensive tests for batched behavior validation. Changes
Sequence DiagramsequenceDiagram
participant WS as WebSocket
participant LPM as LivePerformanceMode
participant Queue as Tip Queue
participant Timer as Batch Timer
participant Batch as applyTipBatch
participant State as Component State
WS->>LPM: tip_received payload
LPM->>LPM: normalizeIncomingTip()
LPM->>Queue: queue tip
LPM->>Timer: start batch timer (TIP_BATCH_WINDOW_MS)
WS->>LPM: tip_received payload (rapid)
LPM->>Queue: queue tip (accumulate)
Timer->>LPM: TIP_BATCH_WINDOW_MS elapsed
LPM->>Batch: flushQueuedTips()
Batch->>Batch: aggregate counts/totals/leaderboard
Batch->>State: apply batch updates at once
State->>State: re-render once per batch
Estimated Code Review Effort🎯 4 (Complex) | ⏱️ ~70 minutes Possibly Related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@frontend/src/components/live-performance/LivePerformanceMode.tsx`:
- Around line 59-79: sanitizeLeaderboard currently synthesizes supporterId from
tipperName when supporterId is missing, which can split a single supporter into
multiple rows; change sanitizeLeaderboard (and the similar logic around the
other block handling entries) to treat a missing or non-string supporterId as a
storage-version mismatch and bail out by returning an empty leaderboard (or
otherwise triggering a rebuild/clear) instead of constructing an identity from
tipperName; ensure you reference the LeaderboardEntry shape and the fields
supporterId, tipperName, total, tipCount, and sortOrder when implementing this
check so the function rejects legacy rows rather than backfilling supporterId.
- Around line 121-123: The current supporterId logic in LivePerformanceMode.tsx
uses raw addresses or the shared 'anonymous' bucket which causes privacy and
leaderboard-merging issues; change supporterId to produce a non-reversible
stable key when a senderAddress exists (e.g., call a helper like
generateStableKey(truncateAddress(...) or the full senderAddress) that returns a
one-way hash) and when tip.isAnonymous or senderAddress is missing, fall back to
the unique tip identifier (tip.tipId) instead of the literal 'anonymous'; update
references to supporterId and add/import the stable-key helper (or use a crypto
hash) so persisted leaderboard identities are non-reversible and unique per tip
when no address is available.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 9e49261a-f0b0-4cac-b43d-2cfcedf21454
⛔ Files ignored due to path filters (1)
frontend/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (8)
frontend/src/components/live-performance/HypeMeter.tsxfrontend/src/components/live-performance/LiveLeaderboard.tsxfrontend/src/components/live-performance/LivePerformanceMode.test.tsxfrontend/src/components/live-performance/LivePerformanceMode.tsxfrontend/src/components/live-performance/LiveTipAlert.tsxfrontend/src/components/live-performance/SessionTicker.tsxfrontend/src/components/live-performance/types.tsfrontend/vite.config.ts
💤 Files with no reviewable changes (1)
- frontend/vite.config.ts
| const sanitizeLeaderboard = (entries: unknown[]): LeaderboardEntry[] => | ||
| entries.map((entry, index) => { | ||
| const candidate = entry as Partial<LeaderboardEntry>; | ||
| const tipperName = | ||
| typeof candidate.tipperName === 'string' && candidate.tipperName.trim() | ||
| ? candidate.tipperName | ||
| : `Supporter ${index + 1}`; | ||
|
|
||
| return { | ||
| supporterId: | ||
| typeof candidate.supporterId === 'string' && candidate.supporterId.trim() | ||
| ? candidate.supporterId | ||
| : tipperName, | ||
| tipperName, | ||
| total: typeof candidate.total === 'number' ? candidate.total : Number(candidate.total) || 0, | ||
| tipCount: typeof candidate.tipCount === 'number' ? candidate.tipCount : Number(candidate.tipCount) || 0, | ||
| sortOrder: | ||
| typeof candidate.sortOrder === 'number' && Number.isFinite(candidate.sortOrder) | ||
| ? candidate.sortOrder | ||
| : index, | ||
| }; |
There was a problem hiding this comment.
Don't migrate legacy leaderboard rows by inventing supporterId from the display label.
Older stored sessions won't have supporterId, so this path backfills the aggregation key from truncated tipperName. The next live tip from the same wallet will then key on senderAddress instead, which means the persisted row no longer matches and the leaderboard can split one supporter into two rows after a refresh. Treat missing supporterId as a storage-version miss and rebuild or clear the leaderboard instead of synthesizing identity from presentation text.
Also applies to: 96-102
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@frontend/src/components/live-performance/LivePerformanceMode.tsx` around
lines 59 - 79, sanitizeLeaderboard currently synthesizes supporterId from
tipperName when supporterId is missing, which can split a single supporter into
multiple rows; change sanitizeLeaderboard (and the similar logic around the
other block handling entries) to treat a missing or non-string supporterId as a
storage-version mismatch and bail out by returning an empty leaderboard (or
otherwise triggering a rebuild/clear) instead of constructing an identity from
tipperName; ensure you reference the LeaderboardEntry shape and the fields
supporterId, tipperName, total, tipCount, and sortOrder when implementing this
check so the function rejects legacy rows rather than backfilling supporterId.
| const tipperName = tip.isAnonymous ? 'Anonymous fan' : truncateAddress(tip.senderAddress || 'Guest fan', 5, 4); | ||
| const supporterId = tip.isAnonymous ? 'anonymous' : tip.senderAddress?.trim() || tipperName; | ||
| const createdAt = typeof tip.createdAt === 'string' ? tip.createdAt : new Date().toISOString(); |
There was a problem hiding this comment.
supporterId should not be a raw address or a shared 'anonymous' bucket.
This value is now the leaderboard identity and gets persisted with the session. For non-anonymous tips, that stores full wallet addresses in localStorage; for anonymous or missing-address tips, every event collapses into the same row because the key is always 'anonymous' or the same fallback. backend/src/websocket/websocket.gateway.ts:168-182 explicitly omits senderAddress for anonymous tips, so that merge will happen in production. Use a non-reversible stable key when an address exists, and fall back to tipId when it does not.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@frontend/src/components/live-performance/LivePerformanceMode.tsx` around
lines 121 - 123, The current supporterId logic in LivePerformanceMode.tsx uses
raw addresses or the shared 'anonymous' bucket which causes privacy and
leaderboard-merging issues; change supporterId to produce a non-reversible
stable key when a senderAddress exists (e.g., call a helper like
generateStableKey(truncateAddress(...) or the full senderAddress) that returns a
one-way hash) and when tip.isAnonymous or senderAddress is missing, fall back to
the unique tip identifier (tip.tipId) instead of the literal 'anonymous'; update
references to supporterId and add/import the stable-key helper (or use a crypto
hash) so persisted leaderboard identities are non-reversible and unique per tip
when no address is available.
close #247
Summary by CodeRabbit
New Features
Improvements