Commit bc27e3c6 authored by Mahmoud Aglan's avatar Mahmoud Aglan

fix: chess unmount cleanup, notification click routing, remove dead disconnect calls

Phase 1.13: add unmountGame export for chess — stops clock, destroys board,
nulls gameState on scene exit.

Phase 5.1: notification items now navigate to relevant section on click
(friends, play, tournaments, achievements based on type).

Phase 6.6: remove remaining stopDisconnectWatch calls from domino/ludo
since disconnect detection is now fully handled by match-session.js.
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 927372c0
import * as scene from '../../core/scene.js'; import * as scene from '../../core/scene.js';
import { mountGame } from './scenes/game.js'; import { mountGame, unmountGame } from './scenes/game.js';
import { mountResult } from './scenes/result.js'; import { mountResult } from './scenes/result.js';
import { mountAnalysis } from './scenes/analysis.js'; import { mountAnalysis } from './scenes/analysis.js';
import { mountHistory } from './scenes/history.js'; import { mountHistory } from './scenes/history.js';
import { mountReview } from './scenes/review.js'; import { mountReview } from './scenes/review.js';
import { mountSpectate } from './scenes/spectate.js'; import { mountSpectate } from './scenes/spectate.js';
scene.register('chess-game', mountGame); scene.register('chess-game', mountGame, unmountGame);
scene.register('chess-result', mountResult); scene.register('chess-result', mountResult);
scene.register('chess-analysis', mountAnalysis); scene.register('chess-analysis', mountAnalysis);
scene.register('chess-history', mountHistory); scene.register('chess-history', mountHistory);
......
...@@ -996,3 +996,8 @@ function reportTournamentResult(result) { ...@@ -996,3 +996,8 @@ function reportTournamentResult(result) {
}).catch(e => console.warn('[tournament] report error:', e)); }).catch(e => console.warn('[tournament] report error:', e));
} }
export function unmountGame() {
if (clock) { clock.stop(); clock = null; }
if (board) { board.destroy?.(); board = null; }
gameState = null;
}
...@@ -1009,7 +1009,7 @@ function endMatch(el, result, reason) { ...@@ -1009,7 +1009,7 @@ function endMatch(el, result, reason) {
state.gameOver = true; state.gameOver = true;
liveSession?.cleanup?.(); liveSession?.cleanup?.();
mp.stopDisconnectWatch?.();
if (result === 'win') { if (result === 'win') {
audio.play('win', 'reward'); audio.play('win', 'reward');
...@@ -1307,7 +1307,7 @@ export function unmountGame() { ...@@ -1307,7 +1307,7 @@ export function unmountGame() {
if (botTimeout) { clearTimeout(botTimeout); botTimeout = null; } if (botTimeout) { clearTimeout(botTimeout); botTimeout = null; }
if (autoPassTimeout) { clearTimeout(autoPassTimeout); autoPassTimeout = null; } if (autoPassTimeout) { clearTimeout(autoPassTimeout); autoPassTimeout = null; }
liveSession?.cleanup?.(); liveSession?.cleanup?.();
mp.stopDisconnectWatch?.();
board?.destroy(); board?.destroy();
hand?.destroy(); hand?.destroy();
drag?.destroy(); drag?.destroy();
......
...@@ -1384,7 +1384,7 @@ async function handleExit(el) { ...@@ -1384,7 +1384,7 @@ async function handleExit(el) {
if (game.mode === 'live' && matchId) { if (game.mode === 'live' && matchId) {
net.post('ludo-match.php', { action: 'leave', match_id: matchId, player_index: myPlayerIndex }).catch(() => {}); net.post('ludo-match.php', { action: 'leave', match_id: matchId, player_index: myPlayerIndex }).catch(() => {});
mp.stopDisconnectWatch();
stopLudoPolling(); stopLudoPolling();
if (heartbeatTimer) { clearInterval(heartbeatTimer); heartbeatTimer = null; } if (heartbeatTimer) { clearInterval(heartbeatTimer); heartbeatTimer = null; }
localStorage.removeItem('el3ab_active_match'); localStorage.removeItem('el3ab_active_match');
......
import * as net from '../../../core/net.js'; import * as net from '../../../core/net.js';
import * as store from '../../../core/store.js'; import * as store from '../../../core/store.js';
import * as scene from '../../../core/scene.js';
import * as bus from '../../../core/bus.js';
import { t } from '../../../core/i18n.js'; import { t } from '../../../core/i18n.js';
export async function mountNotifications(el) { export async function mountNotifications(el) {
...@@ -45,6 +47,24 @@ function renderNotifications(el, notifications) { ...@@ -45,6 +47,24 @@ function renderNotifications(el, notifications) {
notifications.forEach(n => n.is_read = true); notifications.forEach(n => n.is_read = true);
renderNotifications(el, notifications); renderNotifications(el, notifications);
}); });
list.querySelectorAll('.notif-item').forEach(item => {
item.addEventListener('click', () => {
const id = item.dataset.id;
const notif = notifications.find(n => n.id === id);
if (!notif) return;
const type = notif.type || notif.notification_type || '';
if (type === 'friend_request' || type === 'friend_accept') {
bus.emit('navigate', { world: 'social', scene: 'friends' });
} else if (type === 'match_invite' || type === 'challenge') {
bus.emit('navigate', { world: 'play' });
} else if (type === 'tournament') {
bus.emit('navigate', { world: 'tournaments' });
} else if (type === 'achievement') {
scene.push('achievements');
}
});
});
} }
function timeAgo(date) { function timeAgo(date) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment