dubs-server 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +280 -0
- package/CLAUDE.md +46 -0
- package/CONNECT4_PRODUCTION_DEPLOY.md +155 -0
- package/CURRENT_SESSION.md +171 -0
- package/CURRENT_SESSION_DRAW.md +516 -0
- package/MARCH_MADNESS_SURVIVOR.md +254 -0
- package/PANDA.md +166 -0
- package/Procfile +4 -0
- package/README.md +476 -0
- package/controllers/livescoresController.js +376 -0
- package/controllers/pickemController.js +554 -0
- package/controllers/survivorAdminController.js +887 -0
- package/controllers/survivorController.js +623 -0
- package/cron/oracleMonitor.js +77 -0
- package/cron/pickemOracleMonitor.js +73 -0
- package/data/jackpot-history.json +952 -0
- package/data/ncaaTeams.js +406 -0
- package/documentation/API_SECURITY_GUIDE.md +327 -0
- package/documentation/ARCADE_API.md +593 -0
- package/documentation/ARCADE_IMPLEMENTATION_SUMMARY.md +399 -0
- package/documentation/ARCADE_QUICKSTART.md +242 -0
- package/documentation/AUTOMATIC_MODE_ORACLE.md +321 -0
- package/documentation/BUG_FIX_COHORT_DATE_DISPLAY.md +171 -0
- package/documentation/CLAIM_MIGRATION_INSTRUCTIONS.md +52 -0
- package/documentation/CLAIM_STATUS_FIX.md +67 -0
- package/documentation/CLI_TOOL_GUIDE.md +372 -0
- package/documentation/COHORT_RETENTION_ANALYSIS.md +295 -0
- package/documentation/COHORT_RETENTION_IMPLEMENTATION_COMPLETE.md +461 -0
- package/documentation/COHORT_RETENTION_SUMMARY.md +204 -0
- package/documentation/COMPLETE_PROJECT_SUMMARY.md +490 -0
- package/documentation/DATABASE_QUERIES.md +269 -0
- package/documentation/DATABASE_RETENTION_POLICY.md +390 -0
- package/documentation/DATABASE_SETUP_GUIDE.md +361 -0
- package/documentation/DATABASE_SETUP_SUMMARY.md +247 -0
- package/documentation/DEMO_API_CURL_COMMANDS.md +656 -0
- package/documentation/DEPLOYMENT_SUMMARY.txt +100 -0
- package/documentation/DUPLICATE_NOTIFICATIONS_FIXED.md +201 -0
- package/documentation/EXCHANGE_RATES_INTEGRATION.md +371 -0
- package/documentation/FINAL_API_PROTECTION_TABLE.md +175 -0
- package/documentation/GAME_START_NOTIFICATIONS_DEPLOYMENT.md +256 -0
- package/documentation/GAME_START_NOTIFICATIONS_INTEGRATION.md +275 -0
- package/documentation/HEROKU_DEPLOYMENT.md +134 -0
- package/documentation/HEROKU_SCHEDULER_SETUP.md +271 -0
- package/documentation/JACKPOT_API.md +521 -0
- package/documentation/JACKPOT_DEPLOYMENT_GUIDE.md +362 -0
- package/documentation/JWT_IMPLEMENTATION_SUMMARY.md +373 -0
- package/documentation/JWT_QUICK_SETUP.md +268 -0
- package/documentation/JWT_TESTING_GUIDE.md +404 -0
- package/documentation/KEEPER_RECOVERY_GUIDE.md +381 -0
- package/documentation/KEEPER_SETUP.md +206 -0
- package/documentation/KEEPER_STATE_MACHINE.md +423 -0
- package/documentation/LATEST_PRODUCTION_SETUP.md +387 -0
- package/documentation/LOCAL_VOTING_TEST.md +279 -0
- package/documentation/ORACLE_FIXES_SUMMARY.md +188 -0
- package/documentation/ORACLE_POSTGRESQL_UPDATE.md +202 -0
- package/documentation/PAYMENT_DEPLOYMENT.md +209 -0
- package/documentation/PNL_TRACKING_SETUP.md +189 -0
- package/documentation/PREVENTING_LOCKUP_ERRORS.md +472 -0
- package/documentation/PRODUCTION_READY_SUMMARY.md +227 -0
- package/documentation/PUBLIC_VS_PRIVATE_ENDPOINTS.md +278 -0
- package/documentation/QUICK_AUTH_SETUP.md +99 -0
- package/documentation/QUICK_DEPLOY.md +224 -0
- package/documentation/QUICK_FIX.md +114 -0
- package/documentation/QUICK_START.md +152 -0
- package/documentation/REFEREE_MODE_GUIDE.md +392 -0
- package/documentation/RETENTION_CORE_ACTION_UPDATE.md +313 -0
- package/documentation/RETENTION_UPDATE_SUMMARY.md +108 -0
- package/documentation/RUN_MIGRATION_NOW.md +39 -0
- package/documentation/SCRIPTS_UPDATE_SUMMARY.md +251 -0
- package/documentation/SETUP_GUIDE.md +184 -0
- package/documentation/STATE_MACHINE_IMPLEMENTATION.md +250 -0
- package/documentation/TELEGRAM_NOTIFICATIONS_DIAGNOSIS.md +361 -0
- package/documentation/UNIFIED_ARCHITECTURE.md +231 -0
- package/documentation/VOTING_DEPLOYMENT_SUMMARY.md +392 -0
- package/documentation/WEBSOCKET_ARCHITECTURE.md +881 -0
- package/documentation/WHAT_WE_BUILT_TODAY.md +369 -0
- package/documentation/latest/LATEST_PRODUCTION_SETUP.md +865 -0
- package/ecosystem.config.js +65 -0
- package/env.template +125 -0
- package/middleware/apiKeyAuth.js +136 -0
- package/middleware/authenticate.js +214 -0
- package/middleware/developerUserAuth.js +76 -0
- package/middleware/socketAuth.js +69 -0
- package/package.json +49 -0
- package/postman/Dubs-API-v1-With-Voting.postman_collection.json +555 -0
- package/postman/Dubs-API-v1.postman_collection.json +205 -0
- package/postman/Dubs_Developer_API.postman_collection.json +662 -0
- package/postman/QUICKSTART.md +118 -0
- package/postman/QUICK_REFERENCE.md +246 -0
- package/postman/README.md +71 -0
- package/postman/VOTING_API_GUIDE.md +426 -0
- package/refactor/Animations.md +148 -0
- package/refactor/Chat.md +252 -0
- package/routes/actionsRoutes.js +699 -0
- package/routes/adminRoutes.js +370 -0
- package/routes/analyticsRoutes.js +1262 -0
- package/routes/arcadeRoutes.js +557 -0
- package/routes/authRoutes.js +2310 -0
- package/routes/avatarRoutes.js +85 -0
- package/routes/botRoutes.js +211 -0
- package/routes/chatRoutes.js +377 -0
- package/routes/cryptoPriceRoutes.js +105 -0
- package/routes/developerRoutes.js +4201 -0
- package/routes/deviceRoutes.js +214 -0
- package/routes/dmRoutes.js +167 -0
- package/routes/esportsRoutes.js +806 -0
- package/routes/exchangeRateRoutes.js +233 -0
- package/routes/gamesRoutes.js +3028 -0
- package/routes/jackpotRoutes.js +754 -0
- package/routes/keeperMonitoringRoutes.js +156 -0
- package/routes/keeperWebhookRoutes.js +466 -0
- package/routes/livescoresRoutes.js +31 -0
- package/routes/pickemAdminRoutes.js +199 -0
- package/routes/pickemRoutes.js +231 -0
- package/routes/playerStatsRoutes.js +147 -0
- package/routes/portfolioRoutes.js +217 -0
- package/routes/promoRoutes.js +418 -0
- package/routes/referralEarningsRoutes.js +392 -0
- package/routes/socialRoutes.js +459 -0
- package/routes/sportsRoutes.js +1271 -0
- package/routes/survivorAdminRoutes.js +345 -0
- package/routes/survivorRoutes.js +756 -0
- package/routes/uploadRoutes.js +256 -0
- package/routes/userProfileRoutes.js +244 -0
- package/routes/whatsNewRoutes.js +331 -0
- package/scripts/.claude/settings.local.json +15 -0
- package/scripts/README.md +170 -0
- package/scripts/RESTART_EVERYTHING.sh +104 -0
- package/scripts/add-claim-columns.sql +48 -0
- package/scripts/add-crypto-prices-cache.sql +27 -0
- package/scripts/add-exchange-rates-cache.sql +40 -0
- package/scripts/add-game-invite-column.sql +23 -0
- package/scripts/add-game-invite-notification.sql +33 -0
- package/scripts/add-game-invite-telegram-pref.sql +16 -0
- package/scripts/add-game-joined-notification.sql +16 -0
- package/scripts/add-game-joined-pref.js +40 -0
- package/scripts/add-game-joined-preference.sql +6 -0
- package/scripts/add-game-start-notifications.sql +41 -0
- package/scripts/add-notification-flags-to-games.sql +55 -0
- package/scripts/add-pending-game-dismissals.sql +19 -0
- package/scripts/add-preferred-currency.sql +34 -0
- package/scripts/add-winner-columns.js +61 -0
- package/scripts/add_mention_system.sql +53 -0
- package/scripts/add_payment_system.sql +96 -0
- package/scripts/add_sports_event_id_column.sql +22 -0
- package/scripts/analyze-cohort-data-heroku.js +276 -0
- package/scripts/analyze-cohort-data.js +295 -0
- package/scripts/analyze-prod-cohorts.sh +10 -0
- package/scripts/backfill-matchup-images.js +245 -0
- package/scripts/backfill-missing-signatures.js +175 -0
- package/scripts/backfill-referral-earnings.js +202 -0
- package/scripts/check-chat-schema.js +130 -0
- package/scripts/check-db.sh +14 -0
- package/scripts/check_oracle_in_game.js +54 -0
- package/scripts/cleanup-database.js +193 -0
- package/scripts/clear-notification-cache.js +85 -0
- package/scripts/convert-mnemonic.js +50 -0
- package/scripts/create-users-table.sql +44 -0
- package/scripts/debug-cohort-counts.js +248 -0
- package/scripts/debug-winner-calc.js +84 -0
- package/scripts/deploy-payment-system.sh +118 -0
- package/scripts/deploy-to-heroku.sh +63 -0
- package/scripts/diagnose-locked-round.js +143 -0
- package/scripts/dubs-cli.js +720 -0
- package/scripts/dump-account.js +65 -0
- package/scripts/find-vrf-offset.js +48 -0
- package/scripts/fix-chat-notifications-constraint.sql +122 -0
- package/scripts/fix-claim-columns.js +124 -0
- package/scripts/fix-constraint-now.js +44 -0
- package/scripts/fix-lock-timestamps.js +96 -0
- package/scripts/fix-locked-round.sh +126 -0
- package/scripts/fix-missing-badges.sql +91 -0
- package/scripts/fix-payment-notifications.sql +41 -0
- package/scripts/force-new-round.js +55 -0
- package/scripts/force-resolve-and-claim.js +278 -0
- package/scripts/important/README.md +115 -0
- package/scripts/important/authority-force-lock.js +197 -0
- package/scripts/important/authority-resolve-game.js +267 -0
- package/scripts/important/check-game-status.js +373 -0
- package/scripts/important/list-pending-games-by-version.js +270 -0
- package/scripts/important/reconcile-v1-v2-payouts.js +270 -0
- package/scripts/initialize-jackpot.js +111 -0
- package/scripts/jackpot/.claude/settings.local.json +10 -0
- package/scripts/jackpot/force-reset.js +84 -0
- package/scripts/jackpot/initialize-mainnet.js +100 -0
- package/scripts/jackpot/keeper.js +742 -0
- package/scripts/jackpot/status.js +107 -0
- package/scripts/jackpot/update-round-duration.js +143 -0
- package/scripts/keeper-bot.js +112 -0
- package/scripts/list-pending-games.js +131 -0
- package/scripts/migrate-chat-v2.js +127 -0
- package/scripts/migrate-chat-winners.js +84 -0
- package/scripts/migrate-chat.sh +17 -0
- package/scripts/migrate-game-invite.js +83 -0
- package/scripts/migrate-heroku-game-notifications.sh +159 -0
- package/scripts/migrations/001_analytics_tables.sql +422 -0
- package/scripts/migrations/002_add_matchup_image_url.sql +14 -0
- package/scripts/migrations/003_referral_earnings.sql +208 -0
- package/scripts/migrations/004_add_whats_new_notification_type.sql +62 -0
- package/scripts/migrations/005_add_connect4_your_turn_notification.sql +61 -0
- package/scripts/migrations/005_push_notifications.sql +55 -0
- package/scripts/migrations/006_add_draw_team_players.sql +28 -0
- package/scripts/migrations/006_add_game_cancelled_notification.sql +62 -0
- package/scripts/migrations/007_add_gif_url.sql +8 -0
- package/scripts/migrations/008_add_connect4_columns.sql +139 -0
- package/scripts/migrations/008_add_pool_tracking.sql +22 -0
- package/scripts/migrations/009_create_survivor_pool_tables.sql +174 -0
- package/scripts/migrations/010_add_survivor_pool_outcome.sql +28 -0
- package/scripts/migrations/011_create_developer_tables.sql +67 -0
- package/scripts/migrations/011_fix_keeper_tables.sql +85 -0
- package/scripts/migrations/012_create_developer_webhooks.sql +31 -0
- package/scripts/migrations/013_add_network_mode.sql +18 -0
- package/scripts/migrations/014_create_developer_app_users.sql +19 -0
- package/scripts/migrations/015_add_ui_config.sql +4 -0
- package/scripts/migrations/016_add_resolution_secret.sql +4 -0
- package/scripts/migrations/017_add_external_game_id.sql +3 -0
- package/scripts/migrations/018_create_pickem_tables.sql +115 -0
- package/scripts/migrations/019_expo_push_tokens.sql +19 -0
- package/scripts/migrations/create_whats_new_tables.sql +88 -0
- package/scripts/migrations/drop_live_games_tables.sql +34 -0
- package/scripts/open-jackpot-round.js +85 -0
- package/scripts/purge-all-data.sh +329 -0
- package/scripts/purge-all-data.sql +142 -0
- package/scripts/purge-heroku-data.sh +149 -0
- package/scripts/purge-heroku-data.sql +62 -0
- package/scripts/rebuild-heroku-database.sh +113 -0
- package/scripts/recover-funds.js +357 -0
- package/scripts/regenerate-epl-images.js +278 -0
- package/scripts/resize-s3-matchup-images.js +374 -0
- package/scripts/resolve-direct.js +88 -0
- package/scripts/resolve-mock-game.js +124 -0
- package/scripts/resolve-pickem-game.js +55 -0
- package/scripts/resolve-round-manual.js +83 -0
- package/scripts/resolve-stuck-game.js +382 -0
- package/scripts/resolve-stuck-round.js +42 -0
- package/scripts/run-connect4-migration.sh +16 -0
- package/scripts/run-mention-migration.sh +32 -0
- package/scripts/run-payment-migration.sh +51 -0
- package/scripts/run-preferred-currency-migration.sh +31 -0
- package/scripts/run-referral-earnings-migration.sh +32 -0
- package/scripts/run-survivor-outcome-migration.sh +16 -0
- package/scripts/seed-test-users.js +346 -0
- package/scripts/setup-auth-tables.js +78 -0
- package/scripts/setup-complete-database.sql +992 -0
- package/scripts/setup-database-fresh.sh +359 -0
- package/scripts/setup-heroku-keeper.sh +48 -0
- package/scripts/setup-keeper-database.js +83 -0
- package/scripts/setup-keeper-state-db.sql +110 -0
- package/scripts/setup-oracle.sh +39 -0
- package/scripts/setup-pnl-tracking.js +111 -0
- package/scripts/start-devnet.sh +14 -0
- package/scripts/test-arcade-devnet.sh +160 -0
- package/scripts/test-arcade-match.sh +109 -0
- package/scripts/test-automatic-mode.sh +239 -0
- package/scripts/test-connect4-cancel-claim.js +370 -0
- package/scripts/test-connect4-e2e.js +369 -0
- package/scripts/test-connect4-resolve.js +369 -0
- package/scripts/test-game-state-endpoint.js +136 -0
- package/scripts/test-invite-notification.js +86 -0
- package/scripts/test-jackpot-api.sh +71 -0
- package/scripts/test-poll-confirmation.js +267 -0
- package/scripts/test-resolve-game.js +271 -0
- package/scripts/test-resolve-signature.js +223 -0
- package/scripts/test-signature-preservation.js +124 -0
- package/scripts/test-state-machine.js +291 -0
- package/scripts/test-webhook-receiver.js +60 -0
- package/scripts/update-notification-constraint.js +52 -0
- package/scripts/verify-account-layout.js +145 -0
- package/scripts/verify-winner-algorithm.js +278 -0
- package/server.js +5259 -0
- package/services/arcadeMatchService.js +763 -0
- package/services/automaticGameOracle.js +1596 -0
- package/services/chatService.js +1612 -0
- package/services/connect4GameService.js +1049 -0
- package/services/connect4NotificationService.js +374 -0
- package/services/cryptoPriceService.js +223 -0
- package/services/customGameResolver.js +260 -0
- package/services/db.js +79 -0
- package/services/directMessageService.js +389 -0
- package/services/discordNotifications.js +160 -0
- package/services/exchangeRateService.js +289 -0
- package/services/expoPushService.js +314 -0
- package/services/gamesCacheService.js +539 -0
- package/services/jackpotHistory.js +331 -0
- package/services/jackpotService.js +856 -0
- package/services/keeperStateService.js +355 -0
- package/services/matchupImageService.js +591 -0
- package/services/notificationCacheService.js +407 -0
- package/services/pickemOracle.js +440 -0
- package/services/playerStatsService.js +389 -0
- package/services/portfolioService.js +555 -0
- package/services/promoService.js +757 -0
- package/services/promoTreasuryService.js +239 -0
- package/services/pushNotifications.js +353 -0
- package/services/redisService.js +422 -0
- package/services/referralEarningsService.js +728 -0
- package/services/s3Service.js +396 -0
- package/services/socialService.js +1202 -0
- package/services/survivorOracle.js +469 -0
- package/services/survivorSimulator.js +475 -0
- package/services/telegramNotifications.js +461 -0
- package/services/userProfileStatsService.js +1185 -0
- package/services/whatsNewService.js +388 -0
- package/utils/urlHelper.js +95 -0
package/refactor/Chat.md
ADDED
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
# Chat System Refactor
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
This document tracks the optimization work for the Dubs chat system across frontend and backend.
|
|
5
|
+
|
|
6
|
+
**Date**: 2025-02-01
|
|
7
|
+
**Status**: Complete - Ready for Production
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Architecture
|
|
12
|
+
|
|
13
|
+
### Frontend (`dubs-jackpot-spa`)
|
|
14
|
+
|
|
15
|
+
| Component | Location | Purpose |
|
|
16
|
+
|-----------|----------|---------|
|
|
17
|
+
| `ChatWidget.tsx` | `app/v2/components/chat/` | Main orchestrator |
|
|
18
|
+
| `MessageList.tsx` | same | Scrollable container with pagination |
|
|
19
|
+
| `MessageRow.tsx` | same | Individual message with GIF onLoad |
|
|
20
|
+
| `ChatInput.tsx` | same | Input + GIF picker |
|
|
21
|
+
| `ChatContext.tsx` | `app/v2/contexts/` | State management + deduplication |
|
|
22
|
+
| `chatSocket.ts` | `app/v2/services/` | Socket.io singleton |
|
|
23
|
+
|
|
24
|
+
### Backend (`dubs-server`)
|
|
25
|
+
|
|
26
|
+
| File | Purpose |
|
|
27
|
+
|------|---------|
|
|
28
|
+
| `server.js:4005-4758` | Socket.io `/chat` namespace handlers |
|
|
29
|
+
| `services/chatService.js` | Database operations with cursor pagination |
|
|
30
|
+
| `routes/chatRoutes.js` | HTTP endpoints with pagination support |
|
|
31
|
+
| `services/notificationCacheService.js` | Redis caching layer |
|
|
32
|
+
|
|
33
|
+
### Data Flow (Updated)
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
┌──────────────────────────────────────────────────────────────────┐
|
|
37
|
+
│ FRONTEND │
|
|
38
|
+
├──────────────────────────────────────────────────────────────────┤
|
|
39
|
+
│ ChatWidget │
|
|
40
|
+
│ ├── ChatContext (state: messages[], pagination, dedup) │
|
|
41
|
+
│ │ ├── chatSocket.ts (singleton Socket.io client) │
|
|
42
|
+
│ │ └── useToast (rate limit errors) │
|
|
43
|
+
│ ├── MessageList │
|
|
44
|
+
│ │ ├── "Load older messages" button (if hasMore) │
|
|
45
|
+
│ │ ├── Smart scroll (new msgs only, not load more) │
|
|
46
|
+
│ │ └── MessageRow × N │
|
|
47
|
+
│ │ └── <img onLoad={handleImageLoad}> (GIF scroll) │
|
|
48
|
+
│ └── ChatInput → sendMessage() │
|
|
49
|
+
└───────────────────────────┬──────────────────────────────────────┘
|
|
50
|
+
│ Socket.io /chat namespace
|
|
51
|
+
▼
|
|
52
|
+
┌──────────────────────────────────────────────────────────────────┐
|
|
53
|
+
│ BACKEND │
|
|
54
|
+
├──────────────────────────────────────────────────────────────────┤
|
|
55
|
+
│ server.js │
|
|
56
|
+
│ └── chatNamespace.on('send_message') │
|
|
57
|
+
│ ├── Rate limit check (5/min) → "Woah, slow down 🤣" │
|
|
58
|
+
│ ├── chatService.addMessage() → PostgreSQL │
|
|
59
|
+
│ └── chatNamespace.emit('new_message') → ALL clients │
|
|
60
|
+
│ │
|
|
61
|
+
│ GET /chat/messages?limit=20&before={id} │
|
|
62
|
+
│ └── chatService.getRecentMessages(limit, userId, before) │
|
|
63
|
+
│ └── SELECT ... WHERE id < {before} LIMIT {limit+1} │
|
|
64
|
+
│ └── Returns { messages, hasMore, oldestId } │
|
|
65
|
+
└──────────────────────────────────────────────────────────────────┘
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Issues Fixed
|
|
71
|
+
|
|
72
|
+
### Issue #1: Scroll-to-Bottom with GIFs ✅
|
|
73
|
+
|
|
74
|
+
**Problem**: GIFs load asynchronously, scroll happens before GIF height is known.
|
|
75
|
+
|
|
76
|
+
**Solution**:
|
|
77
|
+
- Added `onImageLoad` prop to MessageRow
|
|
78
|
+
- GIF `<img>` has `onLoad={onImageLoad}` handler
|
|
79
|
+
- MessageList checks if user is within 150px of bottom
|
|
80
|
+
- If near bottom, scrolls after GIF loads
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
### Issue #2: Double/Triple Posting ✅
|
|
85
|
+
|
|
86
|
+
**Problem**: Users see duplicate messages (2-3x of same message).
|
|
87
|
+
|
|
88
|
+
**Solution**: Added deduplication in ChatContext:
|
|
89
|
+
```javascript
|
|
90
|
+
setMessages((prev) => {
|
|
91
|
+
if (prev.some(m => m.id === message.id)) {
|
|
92
|
+
console.log('[Chat] Duplicate message ignored:', message.id);
|
|
93
|
+
return prev;
|
|
94
|
+
}
|
|
95
|
+
return [...prev, message];
|
|
96
|
+
});
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
### Issue #3: Loading Too Many Messages ✅
|
|
102
|
+
|
|
103
|
+
**Problem**: Always loaded 100 messages with no pagination.
|
|
104
|
+
|
|
105
|
+
**Solution**:
|
|
106
|
+
- Reduced initial load to 20 messages
|
|
107
|
+
- Added cursor-based pagination (`before` param)
|
|
108
|
+
- "Load older messages" button at top of chat
|
|
109
|
+
- Smart scroll: only scrolls to bottom for new messages, not when loading older
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
### Issue #4: Rate Limit Error Not Shown ✅
|
|
114
|
+
|
|
115
|
+
**Problem**: Users spam chat, get socket error but no UI feedback.
|
|
116
|
+
|
|
117
|
+
**Solution**:
|
|
118
|
+
- Added `useToast` hook to ChatContext
|
|
119
|
+
- Listen for `chat:error` window events
|
|
120
|
+
- Shows friendly toast: "Woah, slow down there 🤣"
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Files Modified
|
|
125
|
+
|
|
126
|
+
| File | Repo | Changes |
|
|
127
|
+
|------|------|---------|
|
|
128
|
+
| `routes/chatRoutes.js` | dubs-server | `before` cursor, `hasMore`/`oldestId` response |
|
|
129
|
+
| `services/chatService.js` | dubs-server | Cursor pagination in `getRecentMessages()` |
|
|
130
|
+
| `server.js` | dubs-server | Friendly rate limit message |
|
|
131
|
+
| `app/v2/contexts/ChatContext.tsx` | dubs-jackpot-spa | Pagination, deduplication, rate limit toast |
|
|
132
|
+
| `app/v2/components/chat/MessageList.tsx` | dubs-jackpot-spa | Load more button, smart scroll, GIF handler |
|
|
133
|
+
| `app/v2/components/chat/MessageRow.tsx` | dubs-jackpot-spa | `onImageLoad` prop for GIFs |
|
|
134
|
+
| `app/v2/components/chat/ChatWidget.tsx` | dubs-jackpot-spa | Pagination props, auto-refresh on panel open |
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Deployment
|
|
139
|
+
|
|
140
|
+
### Order: Backend First, Then Frontend
|
|
141
|
+
|
|
142
|
+
**Why**: Backend changes are backwards compatible. Old frontend works with new backend.
|
|
143
|
+
|
|
144
|
+
### Backend Deploy
|
|
145
|
+
```bash
|
|
146
|
+
cd ~/Developer/iheartsolana/solana-programs/dubs-server
|
|
147
|
+
git add routes/chatRoutes.js services/chatService.js server.js refactor/
|
|
148
|
+
git commit -m "Chat optimization: pagination, rate limit UX"
|
|
149
|
+
git push
|
|
150
|
+
# Deploy to production
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Verify Backend
|
|
154
|
+
```bash
|
|
155
|
+
curl https://api.dubs.gg/chat/messages?limit=5
|
|
156
|
+
# Should return: { hasMore: true, oldestId: X, messages: [...] }
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### Frontend Deploy
|
|
160
|
+
```bash
|
|
161
|
+
cd ~/Developer/iheartsolana/dubs-jackpot-spa
|
|
162
|
+
git add app/v2/contexts/ChatContext.tsx app/v2/components/chat/
|
|
163
|
+
git commit -m "Chat optimization: pagination, deduplication, GIF scroll, rate limit toast"
|
|
164
|
+
git push
|
|
165
|
+
# Deploy frontend
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Backwards Compatibility
|
|
171
|
+
|
|
172
|
+
**Backend**:
|
|
173
|
+
- `before` parameter is optional - old clients work without it
|
|
174
|
+
- New response fields (`hasMore`, `oldestId`) are additive
|
|
175
|
+
- Old clients ignore new fields
|
|
176
|
+
|
|
177
|
+
**Frontend**:
|
|
178
|
+
- Has fallbacks: `data.hasMore ?? false`
|
|
179
|
+
- Old v1 `DegenChat.tsx` still works (uses `limit=50`)
|
|
180
|
+
- New v2 uses `limit=20` with pagination
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Rollback Plan
|
|
185
|
+
|
|
186
|
+
| Scenario | Action |
|
|
187
|
+
|----------|--------|
|
|
188
|
+
| Frontend issues | Revert frontend commit - old frontend works with new backend |
|
|
189
|
+
| Backend issues | Revert backend commit - new frontend has fallbacks |
|
|
190
|
+
| Both | Revert both - system returns to previous state |
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## Future Improvements
|
|
195
|
+
|
|
196
|
+
- [ ] Virtual scrolling for very long chat histories
|
|
197
|
+
- [ ] Preload GIF dimensions from GIPHY API metadata
|
|
198
|
+
- [ ] Message search/filter
|
|
199
|
+
- [ ] Lazy load game invite cards for old messages
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Additional Optimizations
|
|
204
|
+
|
|
205
|
+
### React.memo for MessageRow ✅
|
|
206
|
+
|
|
207
|
+
**Added memoization to prevent unnecessary re-renders:**
|
|
208
|
+
|
|
209
|
+
**MessageRow** (`MessageRow.tsx`):
|
|
210
|
+
```javascript
|
|
211
|
+
export const MessageRow = memo(MessageRowComponent, (prevProps, nextProps) => {
|
|
212
|
+
return (
|
|
213
|
+
prevProps.message.id === nextProps.message.id &&
|
|
214
|
+
prevProps.message.edited === nextProps.message.edited &&
|
|
215
|
+
prevProps.message.reactions === nextProps.message.reactions &&
|
|
216
|
+
prevProps.isHighlighted === nextProps.isHighlighted
|
|
217
|
+
);
|
|
218
|
+
});
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**Note:** GameInviteCard is NOT memoized because it uses `useChat()` context internally for real-time game state updates. Memoizing components that depend heavily on context can cause stale data issues.
|
|
222
|
+
|
|
223
|
+
**Impact:** With 20 messages, new message arrival goes from 20 component re-renders → 1 re-render.
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
### Auto-Refresh on Panel Open ✅
|
|
228
|
+
|
|
229
|
+
**Problem**: Users had to manually pull-to-refresh or reconnect to see new messages when reopening chat.
|
|
230
|
+
|
|
231
|
+
**Solution**: ChatWidget now watches `leadingPanel.isOpen` from ThreePanelLayout:
|
|
232
|
+
|
|
233
|
+
```javascript
|
|
234
|
+
// ChatWidget.tsx
|
|
235
|
+
const { leadingPanel } = useLayout();
|
|
236
|
+
const wasOpenRef = useRef(leadingPanel.isOpen);
|
|
237
|
+
|
|
238
|
+
useEffect(() => {
|
|
239
|
+
// Only refresh when panel transitions from closed to open
|
|
240
|
+
if (leadingPanel.isOpen && !wasOpenRef.current) {
|
|
241
|
+
console.log('[Chat] Panel opened - refreshing messages');
|
|
242
|
+
refreshMessages();
|
|
243
|
+
}
|
|
244
|
+
wasOpenRef.current = leadingPanel.isOpen;
|
|
245
|
+
}, [leadingPanel.isOpen, refreshMessages]);
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
**Behavior**:
|
|
249
|
+
- When user taps chat FAB button to open chat panel
|
|
250
|
+
- Chat automatically fetches fresh messages from API
|
|
251
|
+
- Old messages are replaced with new ones
|
|
252
|
+
- No manual refresh needed
|