- 05 Jun, 2026 38 commits
-
-
Mahmoud Aglan authored
Self-hosted Supabase Kong requires apikey param even for public bucket URLs. Without it, browsers get 401 when loading the image. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Supabase Storage requires both Authorization and apikey headers. The missing apikey caused "No API key found in request" → 500 on upload. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Standard Ludo board: Green(TL), Yellow(TR), Red(BL), Blue(BR) Player order: 0=Red(BL), 1=Green(TL), 2=Yellow(TR), 3=Blue(BR) Path is now CLOCKWISE: - Red enters from bottom center going UP - Green enters from left center going RIGHT - Yellow enters from top center going DOWN - Blue enters from right center going LEFT All positions recalculated from scratch: - SHARED_PATH: 52 squares going clockwise matching reference image - HOME_COLUMNS: each player's 6-square run toward center - HOME_BASES: pieces start in correct corners - START_SQUARES: [0, 13, 26, 39] with correct global positions - Center triangles: point toward center from each player's side - Home zones: correct corner colors - Panel positions: match board layout spatially Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Replace finfo_open with simpler mime_content_type(). Add global exception/error handlers that return JSON instead of HTML error pages. Include curl errors and storage HTTP codes in error responses for debugging. Remove fileinfo from Dockerfile (already bundled in PHP 8.3). Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Add upload_max_filesize=10M to PHP config (default 2M was rejecting compressed images). Add fileinfo extension explicitly. Improve error messages in avatar.php to report the actual failure reason. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Resize any image to 512x512 center-cropped JPEG at 82% quality before uploading. Handles huge photos from phone cameras that would fail or timeout on upload. Removes the 5MB size gate since compression brings all images to ~50-150KB. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The player order was wrong — Blue was assigned to Green's position and vice versa. On a standard Ludo board going clockwise from Red (top-left): Red(TL) → Green(BL) → Yellow(BR) → Blue(TR) Fixed: - COLORS order: red, green, yellow, blue (was red, blue, yellow, green) - HOME_BASES: matched to correct corners - HOME_COLUMNS: Green enters from left, Blue from right - HOME_ENTRY: correct global squares for each player - Center triangles: Red(top), Green(left), Yellow(bottom), Blue(right) - Home zone drawing: correct corner positions - Player panels: top row = Red(TL) + Blue(TR), bottom = Green(BL) + Yellow(BR) Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Player reconnection: - On app boot, checks localStorage for active match - Verifies match is still 'in_progress' on server before rejoining - If match ended/aborted → clears recovery, goes to homepage - If server unreachable → tries to rejoin anyway (optimistic) Match auto-close: - handleGet() checks updated_at timestamp on every poll - If match hasn't been updated in 30+ seconds → both players inactive - Server marks match as 'completed' with result 'aborted' - Next player who polls sees status='completed' → game ends cleanly - Prevents zombie matches lingering forever Flow: 1. Both players disconnect → no pings → updated_at goes stale 2. After 30s, if either player comes back and polls → server closes match 3. Match shows as 'aborted' → player sees 'game ended' UI 4. If only one player comes back within 30s → they keep playing (match alive) Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Replace cluttered logo/level/coins/gems/bell HUD with clean layout: avatar+level badge (left), coins+gems (center), bell (right). Avatar taps navigate to profile. Add profile photo upload with camera badge overlay, client+server validation, Supabase Storage upload endpoint. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
New core module handles ALL connection edge cases: TAB REFRESH RECOVERY: - Active match stored in localStorage with timestamp - On app boot, checks for recoverable match (< 5 min old) - Automatically re-enters the game scene with recovered state - Fetches latest state from server immediately TAB VISIBILITY (switch/minimize): - Pauses polling when tab is hidden (saves bandwidth) - Resumes and immediately fetches latest state on return - Resets disconnect timers on tab return OPPONENT DISCONNECT DETECTION: - Tracks lastOpponentActivity timestamp - After 30s: fires onOpponentDisconnect (show warning UI) - After 60s: fires onOpponentAbandon (auto-claim win) - If opponent comes back: fires onOpponentReconnect NETWORK LOSS HANDLING: - If server unreachable for 10s: fires onConnectionLost - On recovery: fires onConnectionRestored - Polling continues with error tolerance SERVER PING (keep-alive): - Every 10s, pings server with player ID + timestamp - Stored in game_state.ping field - Opponent's polling reads this to know sender is alive API: - create(matchId, gameType, callbacks) — start session - destroy() — clean up timers + localStorage - getRecoverableMatch() — check for resume on boot - markOpponentActive() — call when opponent data received - isConnected() / isOpponentConnected() — status checks Engine updated: - Imports match-session on boot - Checks for recoverable match after auth - Auto-resumes game if found Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Uses contain-fit logic: scales image to fit within the square while preserving natural proportions, centered within the cell. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Game tiles (chess, domino, ludo, backgammon) now get their gradient colors from the theme — editing chess_primary/chess_secondary etc in admin branding immediately changes the homepage tile colors. Also uploaded proper game icons. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Tab bar icons (play, rank, social, shop, profile) now use assetImg() which loads from platform_assets. Uploaded matching PNGs from app icons. Falls back to original SVGs if no custom icons uploaded. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Chess board: - Square colors now read from theme system (getColor) instead of hardcoded constants — editing board colors in admin branding instantly affects all modes (game, analysis, puzzles) Logos: - HUD brand text replaced with assetImg('logo') — shows uploaded PNG - Splash screen uses logo image instead of text - Favicon and apple-touch-icon added to index.php Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
- Pieces now have 10% padding (was 5%) making them visually smaller - Move animation 120ms (was 200ms) with cubic ease-out - Slight squish (85% scale) at midpoint of move - Bigger squish (72% scale) when capturing a piece - Dragging piece slightly smaller (1.1x instead of 1.2x) Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The admin was only reading from local theme.json and platform_theme, but uploaded emoji/asset URLs are stored in platform_assets. Now loads them on page render so the preview thumbnails actually appear. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
When chess piece images are uploaded via admin (chess_piece_wK, chess_piece_bQ, etc.), the board renders them instead of vector paths. Falls back to the original canvas paths if no images are uploaded. Re-renders automatically once images finish loading. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The platform_assets table has no group_name column (unlike platform_theme). This was causing all emoji uploads from admin to silently fail with HTTP 400. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Every admin emoji slot now has a corresponding emoji() or getAsset() call: - Dice faces (1-6): custom dice images replace CSS dots when uploaded - Puzzle themes: fork, pin, castle, crown, sacrifice use emoji() - Particle star: juice engine uses themed particle - Bot thinking dots, book/best-move symbols in classifier - Domino/ludo room icons, chess pawn in leaderboard tabs Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The admin had a 'bell' emoji slot but the HUD used a hardcoded SVG. Now uses emoji('bell', '🔔 ', 18) so uploaded PNGs actually appear. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Three issues fixed: 1. platform_assets insert was missing group_name (likely NOT NULL column, same bug as platform_theme had in 18d0e512) 2. API had Cache-Control: max-age=60 so browser served stale theme data 3. theme.load() silently swallowed errors — added console logging and cache-bust param to diagnose failures Co-Authored-By:
Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Every emoji that has a slot in admin branding now goes through the emoji() function from core/theme.js. Uploading a PNG/SVG replacement in admin will now show up everywhere that emoji appears in the player app. Files updated: hud, multiplayer, player-panel, chess (game/analysis/review/ result/history), ludo (game/result), domino (result), play table, daily rewards, challenges, ranks, shop, leaderboard, tournaments, friends, activity, org (home/browser), profile (view/settings), puzzles. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The emoji() function existed in theme.js but no component imported or called it. All emojis were hardcoded strings. Now result screens, daily rewards, challenges, shop, and history use emoji() which checks for admin-uploaded replacements. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
challenges.php: - Reads challenge_templates from DB instead of hardcoded array - Admin can add/remove/edit challenge types via management panel - Fallback to 3 basic challenges if DB is empty battlepass.php: - Reads active season from 'seasons' table instead of hardcoded config - Admin can create new seasons, set dates, tiers, XP requirements - Fallback to Season 1 defaults if no active season Both APIs now fully driven by database: - Management panel writes to tables → Player app reads automatically - No more hardcoded game config in PHP files Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
image-rendering:-webkit-optimize-contrast caused nearest-neighbor scaling on PNGs making them blocky. Now only applied to SVGs. Also added cache-busting timestamp so re-uploaded assets aren't served stale from browser cache. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
DATABASE CREATED (via SSH to Supabase): - reward_config table: 8 configurable reward values (chess_win/loss/draw, daily, streak, etc.) - seasons table: battle pass season config (name, dates, tiers, xp) - challenge_templates table: 7 challenge types with rewards - award_coins() function: atomic coin grant (prevents race conditions) PLAYER APP CHANGES: 1. Ban enforcement: requireAuth() now checks is_banned + ban_expires_at - Returns 403 'Account banned' if player is banned - Respects expiration dates (temporary bans expire) 2. Economy from config: game.php reads chess_win_coins/draw/loss from reward_config - Admin can change reward values in DB → player app picks them up - No more hardcoded 50/20/10 3. Atomic coin award: calls award_coins() DB function - Single transaction: UPDATE profiles + INSERT economy_transactions - No race condition on concurrent coin grants MANAGEMENT CAN NOW: - Ban a player → immediately blocked from all player app actions - Change reward_config values → player app uses new amounts - Create seasons → player app reads active season from DB - Create challenge templates → player app picks random 3 per day Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Upload was failing because: 1. Missing 'apikey' header on PUT request to Supabase Storage 2. Public URL needs ?apikey= query param for this Supabase instance Fixed: - Added 'apikey: SERVICE_KEY' header to upload curl request - Public URL now includes anon key: .../branding/slot.ext?apikey=ANON_KEY - Browser can load the image directly from this URL - Survives deploys (stored in Supabase Storage, URL in platform_assets) Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Problem: Form POST to same page required PHP session + page re-render. Save appeared to work but values weren't persisting to Supabase reliably. Fix: Save button now POSTs to /api/branding.php directly as JSON. - Collects all input values from DOM - Sends { action: 'save_theme', values: { key: value, ... } } - API writes each value to platform_theme table (upsert) - No session dependency, no form submission, no page reload - Response confirms success/failure with message On page refresh: PHP reads from platform_theme → shows saved values✅ Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
1. REMOVED auto-save entirely - No more saving on every keystroke - Changes tracked as 'dirty' state 2. NEW: Sticky bottom save bar - Shows 'No unsaved changes' (grey) / '
⚠ ️ Unsaved changes' (yellow) - '💾 Save All' button only active when changes exist - Success: '✓ Saved!' feedback - beforeunload warning if leaving with unsaved changes 3. Image uploads now go to Supabase Storage - Uploaded to: profile-images/branding/{slot}.{ext} - Public URL stored in platform_assets table - Survives deploys (not local filesystem) - Also saved locally for immediate preview in admin - Asset URL returned by /api/branding.php GET endpoint 4. Player app reads asset URLs from Supabase - theme.js fetches /api/branding.php → includes assets from platform_assets - Uploaded SVGs/PNGs render at exact specified size - object-fit:contain + image-rendering for no pixelation Flow: - Admin uploads logo.svg → Supabase Storage → URL in platform_assets - Admin changes gold color → marks dirty → clicks Save → Supabase platform_theme - Player loads app → /api/branding.php → gets colors + asset URLs → applies Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
The animateMove method existed on the board but was never called. Game scene was still doing board.setPosition() instantly. Fixed: - Player moves: animateMove(from, to) → piece slides 200ms → then setPosition - Bot moves: same — piece slides smoothly before board updates - Initial position: stays instant (correct — no animation needed on load) The animation method uses requestAnimationFrame to interpolate piece position linearly from source square to destination over 200ms. Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
PROBLEM: Theme was stored in local theme.json inside Docker container. Every deploy rebuilt container → all branding settings LOST. FIX: Dual storage — writes to both local file AND Supabase. Player app reads from Supabase API (persistent). Changes: 1. New API: /api/branding.php - GET: returns full theme from platform_theme + platform_assets tables - POST save_theme: upserts values into platform_theme - POST save_asset: upserts asset URLs into platform_assets - Public endpoint (cached 60s) 2. theme.js updated: - Fetches from /api/branding.php instead of local theme.json - Same apply logic (CSS vars, animations, button shapes) 3. admin/branding.php updated: - Reads from Supabase on page load (not just local file) - Saves to BOTH local file AND Supabase on every edit - Auto-save JS still works (posts to same page → writes to Supabase) Flow: - Admin edits color → auto-save → PHP writes to Supabase + local - Player opens app → theme.js fetches /api/branding.php → Supabase query - Deploy happens → local file reset → Supabase still has all values
✅ - Admin page reloads → reads from Supabase → shows saved values✅ Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
↔ Mahmoud Aglan authoredComprehensive plan documenting: - 11 features player app writes that management can't see - 10 management features player app doesn't integrate with - 7 upgrade phases with estimated ~20 hours total effort - Database functions needed (atomic coin award, ban check) - 7 new management modules needed (rewards-config, seasons, etc.) - Architecture diagram showing both systems' data flow - Security gaps (no rate limit, no ban enforcement, no validation) - Priority-ordered execution plan Based on parallel audits of: - el3ab-management: 38 modules, 425+ routes, tournament/player/economy systems - el3ab-player: 27 API endpoints, tables used, admin visibility needs Key finding: Both systems work independently but critical bridges are missing (tournament registration, match visibility, reward configuration, ban enforcement) Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
PHASE 3 - Ludo Game Feel: - Bot personality profiles (aggressive/casual/strategic per player) - 'يفكر...' thinking indicator during bot turns - Vertical bounce effect during piece hops (-2px offset) - Star burst particles on piece finish - Move preview: ghost circles showing destination for each valid move PHASE 4 - Bot Personalities: - Blue (aggressive): 0.5-1s think, always captures - Yellow (casual): 1.5-3s think, sometimes suboptimal - Green (strategic): 1-2s think, always optimal PHASE 6 - Infrastructure Fixes: - net.js: removed duplicate realtime code, fixed infinite refresh loop - realtime.js: exponential backoff (1s→30s), error logging, connection guard - bus.js: try-catch per listener (one bad listener doesn't break others) PHASE 7 - Chess Polish: - Draw offer implemented (bot: 50% accept, live: sends to server) - Clock fixed: uses performance.now() delta (no more drift) - Piece animation: smooth 200ms tween between squares via requestAnimationFrame PHASE 8 - Player Panel Component: - New reusable core/player-panel.js - Avatar, name, level, rank tier, connection dot, turn indicator - Tap to inspect → popup with add friend button - CSS injected once, used by all games Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Board Layout (matches reference image): - Color order: Red(TL), Blue(TR), Yellow(BR), Green(BL) - Fixed SHARED_PATH: 52 squares going clockwise correctly - Fixed START_SQUARES: [0, 13, 26, 39] — NOW MATCHES rules.js - Fixed HOME_COLUMNS: correct paths toward center per player - Fixed SAFE_SQUARES: match official Ludo star positions - Fixed HOME_ENTRY: correct squares before entering home column Rules Engine fixes: - START_POSITIONS now matches board-map START_SQUARES (was off by 1!) - Capture logic: only checks pieces on shared path (pos < 52) - Home column pieces CANNOT be captured (pos >= BOARD_SIZE check) - Three consecutive 6s = piece goes back home, lose turn - Exact finish requirement enforced (must land exactly on 58) - Extra turn on: rolling 6, capturing, finishing - Bot AI priority fixed: finish > capture > enter > advance furthest Dead code removed: - doMove() cleaned up (was return + unreachable code) Color order fixed in game scene: - COLORS array matches rules.js order - COLORS_LIGHT matches too Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
- 04 Jun, 2026 2 commits
-
-
Mahmoud Aglan authored
Full audit completed by 3 parallel agents examining: - Ludo: 17 critical/major bugs found (capture logic broken, position mismatch) - Chess: 12 critical issues (no server validation, draw unimplemented, clock drift) - Core Infrastructure: 6 critical (duplicate code, infinite loops, race conditions) Implementation plan stored at docs/MULTIPLAYER_OVERHAUL_PLAN.md with: - All issues categorized by severity - Root causes identified - 10-phase execution plan - Estimated ~10 hours of work - Testing matrix Ready to begin Phase 2: Ludo rules/board fix Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-
Mahmoud Aglan authored
Admin auto-save: - Every input change triggers save after 500ms debounce - No more 'Save' button needed — edits are instant - Color picker
↔ text input sync (change one, other updates) - '✓ Saved' indicator flashes on successful save - Uses fetch POST to same page (no reload) Theme loader expanded: - Ludo colors mapped to CSS vars (--ludo-red, --ludo-blue, etc.) - Chess board colors mapped (--board-light, --board-dark, etc.) - All theme values exposed as window.__EL3AB_THEME for JS access - Games can read: window.__EL3AB_THEME?.ludo_red || '#E53935' All edits in admin are now effective: - Platform colors → CSS variables → used by all components - Game colors → CSS variables → used by board renderers - Animation speeds → CSS variables → used by transitions - Button shapes → CSS variables → used by .btn classes - Juice settings → available via getColor() for JS logic - Uploaded assets → served from /public/assets/brand/ Co-Authored-By:Claude Opus 4.6 <noreply@anthropic.com>
-