login fix, lobby fix

This commit is contained in:
2026-02-03 00:16:30 +03:00
parent 038b307d70
commit 73b20c2c54
3 changed files with 217 additions and 15 deletions

65
app.py
View File

@@ -833,6 +833,44 @@ def reset_room(room_code):
return jsonify({'success': True})
@app.route('/api/room/<room_code>/players')
@login_required
def get_room_players(room_code):
"""Получение списка игроков комнаты без перезагрузки страницы"""
room = GameRoom.query.filter_by(code=room_code).first_or_404()
# Проверяем, состоит ли пользователь в комнате
current_player = GamePlayer.query.filter_by(
user_id=current_user.id,
room_id=room.id
).first()
if not current_player:
return jsonify({'error': 'Вы не в этой комнате'}), 403
# Получаем всех игроков
players = GamePlayer.query.filter_by(room_id=room.id).all()
players_data = []
for player in players:
user = User.query.get(player.user_id)
players_data.append({
'user_id': player.user_id,
'username': user.username if user else 'Игрок',
'is_admin': player.is_admin,
'is_ready': player.is_ready,
'capital': player.capital,
'ability_name': get_ability_name(player.ability),
'ability_description': get_ability_description(player.ability)
})
return jsonify({
'success': True,
'players': players_data,
'room_status': room.status
})
@app.route('/room/<room_code>/delete', methods=['POST'])
@login_required
def delete_room(room_code):
@@ -952,16 +990,29 @@ def handle_connect():
@socketio.on('join_room')
def handle_join_room(data):
room_code = data.get('room')
if room_code:
if room_code and current_user.is_authenticated:
join_room(room_code)
logger.info(f'User {current_user.username} joined room {room_code}')
# Отправляем уведомление другим игрокам
emit('player_joined', {
'user_id': current_user.id,
'username': current_user.username,
'timestamp': datetime.utcnow().isoformat()
}, room=room_code, include_self=False)
# Проверяем, было ли уже уведомление о входе
session_key = f'has_notified_join_{room_code}'
if not session.get(session_key):
# Отправляем уведомление другим игрокам
emit('player_joined', {
'user_id': current_user.id,
'username': current_user.username,
'timestamp': datetime.utcnow().isoformat(),
'is_reconnect': False
}, room=room_code, include_self=False)
# Отмечаем в сессии, что уведомление отправлено
session[session_key] = True
else:
# Это реконнект, отправляем тихое обновление
emit('player_reconnected', {
'user_id': current_user.id,
'username': current_user.username
}, room=room_code, include_self=False)
@socketio.on('leave_room')

View File

@@ -423,11 +423,20 @@
{% block scripts %}
<script>
// Глобальные переменные
// Не объявляем socket заново, он уже объявлен в base.html
// let socket = io(); // УБРАТЬ эту строку!
let roomCode = '{{ room.code }}';
let currentPlayerId = '{{ current_player.id }}';
let isAdmin = {{ 'true' if current_player.is_admin else 'false' }};
let lastNotificationTime = 0; // Для ограничения частоты уведомлений
window.roomStatus = '{{ room.status }}'; // Добавьте эту строку
// Функция форматирования валюты
function formatCurrency(amount) {
return new Intl.NumberFormat('ru-RU', {
style: 'currency',
currency: 'RUB',
minimumFractionDigits: 0
}).format(amount);
}
// Инициализация при загрузке
document.addEventListener('DOMContentLoaded', function() {
@@ -493,11 +502,39 @@ if (typeof socket !== 'undefined') {
});
socket.on('player_joined', function(data) {
console.log('Player joined:', data.username);
showNotification(`🎮 ${data.username} присоединился к комнате`);
console.log('Player joined:', data.username, data);
// Проверяем, не текущий ли это пользователь
if (data.user_id && data.user_id == currentPlayerId) {
console.log('Это текущий пользователь, игнорируем');
return;
}
// Проверяем, не было ли уже уведомления
if (window.lastJoinNotification === data.user_id + '_' + new Date().toISOString().slice(0, 10)) {
console.log('Уведомление уже показывалось сегодня');
return;
}
// Показываем уведомление
showNotification(`🎮 ${data.username} присоединился к комнате`);
// Обновляем список игроков без перезагрузки
setTimeout(() => {
updatePlayerList();
}, 500);
// Запоминаем, что показали уведомление
window.lastJoinNotification = data.user_id + '_' + new Date().toISOString().slice(0, 10);
});
socket.on('player_reconnected', function(data) {
console.log('Player reconnected:', data.username);
// Не показываем уведомление для реконнекта
// Просто обновляем список
setTimeout(() => {
location.reload();
}, 1000);
updatePlayerList();
}, 500);
});
socket.on('player_left', function(data) {
@@ -897,7 +934,20 @@ function updateRoomStatus() {
}
function showNotification(message, type = 'info') {
// Ограничиваем частоту уведомлений (не чаще 1 раза в 3 секунды)
const now = Date.now();
if (now - lastNotificationTime < 3000) {
console.log('Notification throttled');
return;
}
lastNotificationTime = now;
// Скрываем предыдущие уведомления
const oldNotifications = document.querySelectorAll('.custom-notification');
oldNotifications.forEach(n => n.remove());
const notification = document.createElement('div');
notification.className = 'custom-notification';
notification.style.cssText = `
position: fixed;
top: 80px;
@@ -911,6 +961,7 @@ function showNotification(message, type = 'info') {
animation: slideInRight 0.3s ease;
max-width: 300px;
word-break: break-word;
transition: opacity 0.3s;
`;
if (type === 'success') notification.style.borderLeftColor = 'var(--success-color)';
@@ -920,8 +971,9 @@ function showNotification(message, type = 'info') {
notification.textContent = message;
document.body.appendChild(notification);
// Автоматическое скрытие через 3 секунды
setTimeout(() => {
notification.style.animation = 'slideOutRight 0.3s ease';
notification.style.opacity = '0';
setTimeout(() => notification.remove(), 300);
}, 3000);
}
@@ -958,6 +1010,105 @@ if (chatMessages) {
if (chatInput) chatInput.focus();
});
}
window.addEventListener('beforeunload', function() {
if (typeof socket !== 'undefined' && socket.connected && roomCode) {
socket.emit('leave_room', { room: roomCode });
}
});
// Обработка видимости страницы (если переключились на другую вкладку)
document.addEventListener('visibilitychange', function() {
if (document.hidden) {
console.log('Page is now hidden');
} else {
console.log('Page is now visible');
// При возвращении на страницу проверяем статус
updateRoomStatus();
}
});
// Функция обновления списка игроков без перезагрузки страницы
function updatePlayerList() {
console.log('Updating player list...');
fetch(`/api/room/${roomCode}/players`)
.then(response => response.json())
.then(data => {
if (data.success && data.players) {
updatePlayerListUI(data.players);
updateReadyStatus();
}
})
.catch(error => {
console.error('Error updating player list:', error);
// В случае ошибки делаем мягкую перезагрузку через 2 секунды
setTimeout(() => {
location.reload();
}, 2000);
});
}
// Функция обновления UI списка игроков
function updatePlayerListUI(players) {
const playerList = document.getElementById('player-list');
if (!playerList) return;
playerList.innerHTML = '';
players.forEach(player => {
const li = document.createElement('li');
li.className = 'player-item';
li.innerHTML = `
<div class="player-info">
<div class="player-avatar" style="background-color: ${player.is_admin ? '#ff9800' : 'var(--primary-color)'};">
${player.username ? player.username[0].toUpperCase() : '?'}
</div>
<div>
<div style="display: flex; align-items: center; gap: 5px;">
<strong>${player.username || 'Игрок'}</strong>
${player.is_admin ? '<span style="background-color: #fff3e0; color: #ef6c00; padding: 2px 6px; border-radius: 10px; font-size: 0.75rem;">Админ</span>' : ''}
${player.user_id == currentPlayerId ? '<span style="background-color: #e3f2fd; color: #1976d2; padding: 2px 6px; border-radius: 10px; font-size: 0.75rem;">Вы</span>' : ''}
</div>
<div class="player-capital">
${formatCurrency(player.capital)}
</div>
</div>
</div>
<div>
${window.roomStatus === 'waiting' ? `
<div class="player-ready ${player.is_ready ? 'ready' : 'not-ready'}">
${player.is_ready ? '✅ Готов' : '⏳ Ожидание'}
</div>
` : ''}
<div class="player-ability" title="${player.ability_description}">
${player.ability_name}
</div>
</div>
`;
playerList.appendChild(li);
});
}
// Обработка дисконнекта WebSocket
socket.on('disconnect', function(reason) {
console.log('WebSocket disconnected:', reason);
if (reason === 'io server disconnect') {
// Сервер намеренно отключил
showNotification('🔌 Соединение с сервером потеряно. Переподключаемся...', 'warning');
}
});
// Периодическая проверка подключения
setInterval(() => {
if (socket && !socket.connected) {
console.log('Socket not connected, attempting to reconnect...');
socket.connect();
}
}, 5000);
</script>
<style>

View File

@@ -2,7 +2,7 @@
{% block title %}Вход - Капитал & Рынок{% endblock %}
{% block screen_content %}
{% block content %}
<div class="header">
<div class="logo-container">
<img src="{{ url_for('static', filename='images/logo.png') }}" alt="Капитал & Рынок" class="logo">