cleanup
This commit is contained in:
parent
ea36b0d535
commit
b92de5c0fd
195
static/app.js
195
static/app.js
@ -1,4 +1,6 @@
|
||||
// ==================== CONFIGURATION ====================
|
||||
// noinspection HtmlUnknownTarget
|
||||
|
||||
const CONFIG = {
|
||||
OUTPUT: {
|
||||
ECHO_CANCELLATION: true,
|
||||
@ -374,7 +376,6 @@ class Utils {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ username: username })
|
||||
});
|
||||
if (!response.ok) throw new Error('Network response was not ok');
|
||||
const data = await response.json();
|
||||
return { available: data.available, error: data.error };
|
||||
} catch (error) {
|
||||
@ -431,16 +432,16 @@ class UIManager {
|
||||
document.body.appendChild(notice);
|
||||
}
|
||||
static removeReconnectionNotice() {
|
||||
const notice = document.getElementById('reconnection-notice');
|
||||
const notice = $('#reconnection-notice');
|
||||
if (notice) notice.remove();
|
||||
}
|
||||
static updateMicrophoneStatus(granted) {
|
||||
const micStatus = document.getElementById('mic-status');
|
||||
const micStatus = $('#mic-status');
|
||||
if (!micStatus) return;
|
||||
if (granted) {
|
||||
micStatus.textContent = '✅ Microphone access granted';
|
||||
micStatus.className = 'mic-status granted';
|
||||
document.getElementById('mic-section').style.display = 'none';
|
||||
$('#mic-section').style.display = 'none';
|
||||
} else {
|
||||
micStatus.textContent = '❌ Microphone access denied. Please refresh and allow microphone access.';
|
||||
micStatus.innerHTML = micStatus.textContent.replace('. ', '.<br>');
|
||||
@ -448,47 +449,44 @@ class UIManager {
|
||||
}
|
||||
}
|
||||
static updateJoinButton(text, disabled = false) {
|
||||
const joinBtn = document.getElementById('join-chat-btn');
|
||||
const joinBtn = $('#join-chat-btn');
|
||||
joinBtn.textContent = text;
|
||||
joinBtn.disabled = disabled;
|
||||
}
|
||||
static showVoiceChatUI() {
|
||||
document.getElementById('join-section').style.display = 'none';
|
||||
document.getElementById('username-section').style.display = 'none';
|
||||
document.getElementById('voice-controls-sidebar').style.display = 'block';
|
||||
document.getElementById('chat-section').style.display = 'flex';
|
||||
$('#join-section').style.display = 'none';
|
||||
$('#username-section').style.display = 'none';
|
||||
$('#voice-controls-sidebar').style.display = 'block';
|
||||
$('#chat-section').style.display = 'flex';
|
||||
}
|
||||
static showUsernameUI() {
|
||||
document.getElementById('join-section').style.display = 'flex';
|
||||
document.getElementById('username-section').style.display = 'block';
|
||||
document.getElementById('voice-controls-sidebar').style.display = 'none';
|
||||
document.getElementById('chat-section').style.display = 'none';
|
||||
document.getElementById('users-list').innerHTML = '<div class="no-users"></div>';
|
||||
$('#join-section').style.display = 'flex';
|
||||
$('#username-section').style.display = 'block';
|
||||
$('#voice-controls-sidebar').style.display = 'none';
|
||||
$('#chat-section').style.display = 'none';
|
||||
$('#users-list').innerHTML = '<div class="no-users"></div>';
|
||||
}
|
||||
static handleClickOutsideEmojiPicker(event) {
|
||||
const emojiPicker = document.getElementById('emoji-picker');
|
||||
const emojiPicker = $('#emoji-picker');
|
||||
if (!emojiPicker.contains(event.target)) {
|
||||
UIManager.closeEmojiPicker();
|
||||
}
|
||||
}
|
||||
|
||||
static closeEmojiPicker() {
|
||||
const emojiPicker = document.getElementById('emoji-picker');
|
||||
const emojiPicker = $('#emoji-picker');
|
||||
if (emojiPicker) {
|
||||
emojiPicker.remove();
|
||||
document.removeEventListener('click', UIManager.handleClickOutsideEmojiPicker);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static openEmojiPicker() {
|
||||
if (document.getElementById('emoji-picker')) {
|
||||
if ($('#emoji-picker')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const chatSection = document.getElementById('chat-messages');
|
||||
const chatInputContainer = $('.chat-input-container');
|
||||
const emojiBtn = document.getElementById('emoji-btn');
|
||||
|
||||
// Create emoji picker container
|
||||
const emojiPicker = document.createElement('div');
|
||||
@ -516,7 +514,7 @@ class UIManager {
|
||||
// Add emojis to the picker
|
||||
EMOJIS.forEach(emoji => {
|
||||
const emojiSpan = document.createElement('span');
|
||||
const sendBtn = document.getElementById('send-btn');
|
||||
const sendBtn = $('#send-btn');
|
||||
emojiSpan.className = 'emoji';
|
||||
emojiSpan.textContent = emoji;
|
||||
emojiSpan.style.cursor = 'pointer';
|
||||
@ -526,7 +524,7 @@ class UIManager {
|
||||
emojiSpan.style.fontSize = '1.5rem';
|
||||
emojiSpan.style.borderRadius = '0.5rem';
|
||||
emojiSpan.onclick = () => {
|
||||
const messageInput = document.getElementById('chat-input');
|
||||
const messageInput = $('#chat-input');
|
||||
messageInput.value += emoji;
|
||||
messageInput.focus();
|
||||
sendBtn.disabled = messageInput.value.trim() === '';
|
||||
@ -554,7 +552,7 @@ class UIManager {
|
||||
}
|
||||
|
||||
static toggleEmojiPicker() {
|
||||
if (document.getElementById('emoji-picker')) {
|
||||
if ($('#emoji-picker')) {
|
||||
UIManager.closeEmojiPicker();
|
||||
} else {
|
||||
UIManager.openEmojiPicker();
|
||||
@ -562,19 +560,19 @@ class UIManager {
|
||||
}
|
||||
|
||||
static async loadSettingsButton() {
|
||||
const settingsBtn = document.getElementById('voice-settings-btn');
|
||||
const settingsBtn = $('#voice-settings-btn');
|
||||
settingsBtn.innerHTML = await RenderSvg(SVGS.SETTINGS);
|
||||
settingsBtn.title = 'Settings';
|
||||
}
|
||||
|
||||
static async loadDisconnectButton() {
|
||||
const disconnectBtn = document.getElementById('leave-voice-btn');
|
||||
const disconnectBtn = $('#leave-voice-btn');
|
||||
disconnectBtn.innerHTML = await RenderSvg(SVGS.CONNECT);
|
||||
disconnectBtn.title = 'Disconnect';
|
||||
}
|
||||
|
||||
static async updateMuteButton() {
|
||||
const muteBtn = document.getElementById('toggle-mute-btn');
|
||||
const muteBtn = $('#toggle-mute-btn');
|
||||
if (state.isMuted) {
|
||||
muteBtn.innerHTML = await RenderSvg(SVGS.MUTED);
|
||||
muteBtn.title = 'Unmute (enable outgoing audio)';
|
||||
@ -589,7 +587,7 @@ class UIManager {
|
||||
}
|
||||
}
|
||||
static async updateDeafenButton() {
|
||||
const deafenBtn = document.getElementById('toggle-deafen-btn');
|
||||
const deafenBtn = $('#toggle-deafen-btn');
|
||||
if (state.isDeafened) {
|
||||
deafenBtn.innerHTML = await RenderSvg(SVGS.DEAFENED);
|
||||
deafenBtn.title = 'Undeafen (enable incoming audio)';
|
||||
@ -720,8 +718,7 @@ class AudioManager {
|
||||
// New: Update microphone gain
|
||||
static updateMicrophoneGain() {
|
||||
if (state.micGainNode) {
|
||||
const gainValue = state.micVolume / CONFIG.MEDIA.MAX_VOLUME;
|
||||
state.micGainNode.gain.value = gainValue;
|
||||
state.micGainNode.gain.value = state.micVolume / CONFIG.MEDIA.MAX_VOLUME;
|
||||
} else {
|
||||
console.warn('🎤 Cannot update microphone gain - no gain node available');
|
||||
}
|
||||
@ -811,7 +808,7 @@ class AudioManager {
|
||||
state.localStream = null;
|
||||
|
||||
await Utils.delay(100);
|
||||
const newStream = await navigator.mediaDevices.getUserMedia({
|
||||
state.localStream = await navigator.mediaDevices.getUserMedia({
|
||||
audio: {
|
||||
echoCancellation: CONFIG.OUTPUT.ECHO_CANCELLATION,
|
||||
noiseSuppression: CONFIG.OUTPUT.NOISE_SUPPRESSION,
|
||||
@ -820,7 +817,6 @@ class AudioManager {
|
||||
deviceId: CONFIG.OUTPUT.DEVICE_ID,
|
||||
}
|
||||
});
|
||||
state.localStream = newStream;
|
||||
|
||||
// Set up audio processing again
|
||||
await AudioManager.setupAudioProcessing();
|
||||
@ -863,7 +859,7 @@ class AudioManager {
|
||||
audioElement.volume = (state.headphoneVolume / CONFIG.MEDIA.MAX_VOLUME) * (userVolume / CONFIG.MEDIA.MAX_VOLUME);
|
||||
audioElement.muted = state.isDeafened || state.mutedUsers.has(userId);
|
||||
AudioManager.setupAudioEventListeners(audioElement, userId);
|
||||
document.getElementById('audio-container').appendChild(audioElement);
|
||||
$('#audio-container').appendChild(audioElement);
|
||||
audioElement.play().then(() => {
|
||||
console.log('🔊 Successfully started playing audio for user:', userId);
|
||||
}).catch(error => {
|
||||
@ -933,10 +929,12 @@ class WebSocketManager {
|
||||
switch (message.type) {
|
||||
case 'system_message':
|
||||
ChatManager.addChatAlert(message.data, message.dataType, message.dataTime);
|
||||
break;
|
||||
case 'client_id':
|
||||
console.log('🔑 Client ID received:', message.clientId);
|
||||
state.currentId = message.clientId;
|
||||
state.save();
|
||||
break;
|
||||
case 'users_list':
|
||||
console.log('🔵 This is a users_list message with data:', message.data);
|
||||
UserManager.updateUsersList(message.data);
|
||||
@ -974,8 +972,8 @@ class WebSocketManager {
|
||||
if (state.isInVoiceChat) {
|
||||
console.log('🔄 Server connection lost, resetting client state...');
|
||||
PeerConnectionManager.cleanupAllConnections();
|
||||
document.getElementById('audio-container').innerHTML = '';
|
||||
document.getElementById('users-list').innerHTML = '<div class="no-users"></div>';
|
||||
$('#audio-container').innerHTML = '';
|
||||
$('#users-list').innerHTML = '<div class="no-users"></div>';
|
||||
const savedUsername = state.currentUsername;
|
||||
state.isInVoiceChat = false;
|
||||
if (!state.intentionalDisconnect) {
|
||||
@ -1328,7 +1326,7 @@ class UserManager {
|
||||
users = [];
|
||||
}
|
||||
|
||||
const usersList = document.getElementById('users-list');
|
||||
const usersList = $('#users-list');
|
||||
const currentUserIds = users.map(u => u.id);
|
||||
const previousUserIds = Object.keys(state.previousUsers);
|
||||
|
||||
@ -1340,12 +1338,12 @@ class UserManager {
|
||||
}
|
||||
|
||||
static setUsername() {
|
||||
const modalUsernameInput = document.getElementById('modal-username-input');
|
||||
const usernameInput = document.getElementById('username-input');
|
||||
const modalUsernameInput = $('#modal-username-input');
|
||||
const usernameInput = $('#username-input');
|
||||
|
||||
const username = modalUsernameInput.value.trim();
|
||||
|
||||
if (username == state.currentUsername) {
|
||||
if (username === state.currentUsername) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1418,7 +1416,7 @@ class UserManager {
|
||||
static detectUserChanges(users, currentUserIds, previousUserIds) {
|
||||
if (state.previousUsers && state.isInVoiceChat) {
|
||||
const newUsers = users ? users.filter(u => !previousUserIds.includes(u.id) && u.username !== state.currentUsername) : [];
|
||||
newUsers.forEach(user => {
|
||||
newUsers.forEach(_ => {
|
||||
Utils.playSound('/sounds/join.wav', state.apparentOutputVolume());
|
||||
});
|
||||
const leftUserIds = previousUserIds.filter(id => !currentUserIds.includes(id));
|
||||
@ -1466,7 +1464,7 @@ class UserManager {
|
||||
|
||||
const clickHandler = isCurrentUser ? `onclick="ModalManager.openSelfModal()"` : `onclick="ModalManager.openUserModal('${user.id}', '${user.username}')"`;
|
||||
const muteButtonHtml = !isCurrentUser ? `
|
||||
<button class="mute-user-btn" onclick="event.stopPropagation(); VoiceControls.muteUser('${user.id}'); const muteBtn = document.getElementById('modal-mute-btn'); const isMuted = state.mutedUsers.has('${user.id}'); muteBtn.textContent = isMuted ? '🔇 User Muted' : '🔊 Mute User'; muteBtn.className = isMuted ? 'control-btn muted' : 'control-btn';" title="${isMuted ? 'Unmute user' : 'Mute user'}">
|
||||
<button class="mute-user-btn" onclick="event.stopPropagation(); VoiceControls.muteUser('${user.id}'); const muteBtn = $('#modal-mute-btn'); const isMuted = state.mutedUsers.has('${user.id}'); muteBtn.textContent = isMuted ? '🔇 User Muted' : '🔊 Mute User'; muteBtn.className = isMuted ? 'control-btn muted' : 'control-btn';" title="${isMuted ? 'Unmute user' : 'Mute user'}">
|
||||
${isMuted ? '🔇' : '🔊'}
|
||||
</button>
|
||||
` : '';
|
||||
@ -1535,7 +1533,7 @@ class UserManager {
|
||||
// ==================== CHAT MANAGEMENT ====================
|
||||
class ChatManager {
|
||||
static handleChatMessage(data) {
|
||||
const chatMessages = document.getElementById('chat-messages');
|
||||
const chatMessages = $('#chat-messages');
|
||||
const isOwnMessage = data.username === state.currentUsername;
|
||||
let message = '';
|
||||
let timestamp = Date.now();
|
||||
@ -1553,8 +1551,7 @@ class ChatManager {
|
||||
}
|
||||
const messageEl = document.createElement('div');
|
||||
messageEl.className = `chat-message ${isOwnMessage ? 'own' : 'other'}`;
|
||||
const messageId = `msg_${Date.now()}_${Math.random()}`;
|
||||
messageEl.id = messageId;
|
||||
messageEl.id = `msg_${Date.now()}_${Math.random()}`;
|
||||
messageEl.innerHTML = `
|
||||
<div class="chat-message-header">
|
||||
<div class="username">${isOwnMessage ? 'You' : data.username}</div>
|
||||
@ -1567,7 +1564,7 @@ class ChatManager {
|
||||
console.log('Added chat message from:', data.username, 'message:', message);
|
||||
}
|
||||
static addChatAlert(message, type, timeout) {
|
||||
const chatMessages = document.getElementById('chat-messages');
|
||||
const chatMessages = $('#chat-messages');
|
||||
if (!chatMessages) return;
|
||||
const alertEl = document.createElement('div');
|
||||
alertEl.className = `chat-alert chat-alert-${type}`;
|
||||
@ -1594,7 +1591,7 @@ class ChatManager {
|
||||
}
|
||||
|
||||
static deleteMessage(messageId) {
|
||||
const messageEl = document.getElementById(messageId);
|
||||
const messageEl = $(messageId);
|
||||
if (messageEl) {
|
||||
messageEl.classList.add('fading');
|
||||
setTimeout(() => {
|
||||
@ -1602,7 +1599,7 @@ class ChatManager {
|
||||
messageEl.remove();
|
||||
}
|
||||
state.messageTimeouts.delete(messageId);
|
||||
}, 1000);
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1657,8 +1654,8 @@ class VoiceControls {
|
||||
state.save();
|
||||
}
|
||||
static updateMicVolume() {
|
||||
const slider = document.getElementById('mic-volume-slider');
|
||||
const percentage = document.getElementById('mic-volume-percentage');
|
||||
const slider = $('#mic-volume-slider');
|
||||
const percentage = $('#mic-volume-percentage');
|
||||
state.micVolume = parseInt(slider.value);
|
||||
percentage.textContent = `${state.micVolume}%`;
|
||||
|
||||
@ -1666,8 +1663,8 @@ class VoiceControls {
|
||||
AudioManager.updateMicrophoneGain();
|
||||
}
|
||||
static updateHeadphoneVolume() {
|
||||
const slider = document.getElementById('headphone-volume-slider');
|
||||
const percentage = document.getElementById('headphone-volume-percentage');
|
||||
const slider = $('#headphone-volume-slider');
|
||||
const percentage = $('#headphone-volume-percentage');
|
||||
state.headphoneVolume = parseInt(slider.value);
|
||||
percentage.textContent = `${state.headphoneVolume}%`;
|
||||
const audioElements = $$('#audio-container audio');
|
||||
@ -1680,10 +1677,10 @@ class VoiceControls {
|
||||
static resetAllVolumes() {
|
||||
state.micVolume = 100;
|
||||
state.headphoneVolume = 100;
|
||||
const micSlider = document.getElementById('mic-volume-slider');
|
||||
const headphoneSlider = document.getElementById('headphone-volume-slider');
|
||||
const micPercentage = document.getElementById('mic-volume-percentage');
|
||||
const headphonePercentage = document.getElementById('headphone-volume-percentage');
|
||||
const micSlider = $('#mic-volume-slider');
|
||||
const headphoneSlider = $('#headphone-volume-slider');
|
||||
const micPercentage = $('#mic-volume-percentage');
|
||||
const headphonePercentage = $('#headphone-volume-percentage');
|
||||
if (micSlider) {
|
||||
micSlider.value = 100;
|
||||
micPercentage.textContent = '100%';
|
||||
@ -1701,10 +1698,10 @@ class VoiceControls {
|
||||
// ==================== MODAL MANAGEMENT ====================
|
||||
class ModalManager {
|
||||
static openSelfModal() {
|
||||
const modal = document.getElementById('user-control-modal');
|
||||
const modalUsername = document.getElementById('modal-username');
|
||||
const modal = $('#user-control-modal');
|
||||
const modalUsername = $('#modal-username');
|
||||
modalUsername.textContent = 'Settings';
|
||||
const percentage = document.getElementById('headphone-volume-percentage');
|
||||
const percentage = $('#headphone-volume-percentage');
|
||||
if (percentage) {
|
||||
percentage.textContent = `${state.headphoneVolume}%`;
|
||||
}
|
||||
@ -1713,8 +1710,8 @@ class ModalManager {
|
||||
<div class="control-section">
|
||||
<h1>Username</h1>
|
||||
<div class="modal-username">
|
||||
<input type="text" id="modal-username-input" placeholder="Enter your username" value="${state.currentUsername}"></input>
|
||||
<input type="button" value="Apply" class="control-btn secondary" onclick="UserManager.setUsername()"></input>
|
||||
<input type="text" id="modal-username-input" placeholder="Enter your username" value="${state.currentUsername}">
|
||||
<input type="button" value="Apply" class="control-btn secondary" onclick="UserManager.setUsername()">
|
||||
</div >
|
||||
</div>
|
||||
<div class="control-section">
|
||||
@ -1744,7 +1741,7 @@ class ModalManager {
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
const modalUsernameInput = document.getElementById('modal-username-input');
|
||||
const modalUsernameInput = $('#modal-username-input');
|
||||
modalUsernameInput.addEventListener('keydown', (event) => {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
@ -1755,15 +1752,15 @@ class ModalManager {
|
||||
console.log('Opened self audio settings modal');
|
||||
}
|
||||
// static closeSelfModal() {
|
||||
// const modal = document.getElementById('user-control-modal');
|
||||
// const modal = $('#user-control-modal');
|
||||
// modal.style.display = 'none';
|
||||
// state.currentModalUserId = null;
|
||||
// console.log('Closed self audio settings modal');
|
||||
// }
|
||||
static openUserModal(userId, username) {
|
||||
state.currentModalUserId = userId;
|
||||
const modal = document.getElementById('user-control-modal');
|
||||
const modalUsername = document.getElementById('modal-username');
|
||||
const modal = $('#user-control-modal');
|
||||
const modalUsername = $('#modal-username');
|
||||
modalUsername.textContent = `${username} `;
|
||||
const modalBody = modal.querySelector('.modal-body');
|
||||
modalBody.innerHTML = `
|
||||
@ -1787,11 +1784,11 @@ class ModalManager {
|
||||
</div>
|
||||
`;
|
||||
const currentVolume = state.userVolumes.get(userId) || 100;
|
||||
const volumeSlider = document.getElementById('user-volume-slider');
|
||||
const volumePercentage = document.getElementById('volume-percentage');
|
||||
const volumeSlider = $('#user-volume-slider');
|
||||
const volumePercentage = $('#volume-percentage');
|
||||
volumeSlider.value = currentVolume;
|
||||
volumePercentage.textContent = `${currentVolume}% `;
|
||||
const muteBtn = document.getElementById('modal-mute-btn');
|
||||
const muteBtn = $('#modal-mute-btn');
|
||||
const isMuted = state.mutedUsers.has(userId);
|
||||
if (muteBtn) {
|
||||
muteBtn.textContent = isMuted ? '🔇 User Muted' : '🔊 Mute User';
|
||||
@ -1801,15 +1798,15 @@ class ModalManager {
|
||||
console.log(`Opened modal for user ${username}(${userId})`);
|
||||
}
|
||||
static closeUserModal() {
|
||||
const modal = document.getElementById('user-control-modal');
|
||||
const modal = $('#user-control-modal');
|
||||
modal.style.display = 'none';
|
||||
state.currentModalUserId = null;
|
||||
console.log('Closed user modal');
|
||||
}
|
||||
static updateUserVolume() {
|
||||
if (!state.currentModalUserId) return;
|
||||
const slider = document.getElementById('user-volume-slider');
|
||||
const volumePercentage = document.getElementById('volume-percentage');
|
||||
const slider = $('#user-volume-slider');
|
||||
const volumePercentage = $('#volume-percentage');
|
||||
const volume = parseInt(slider.value);
|
||||
volumePercentage.textContent = `${volume}% `;
|
||||
state.userVolumes.set(state.currentModalUserId, volume);
|
||||
@ -1829,15 +1826,15 @@ class ModalManager {
|
||||
static toggleUserMuteFromModal() {
|
||||
if (!state.currentModalUserId) return;
|
||||
VoiceControls.muteUser(state.currentModalUserId);
|
||||
const muteBtn = document.getElementById('modal-mute-btn');
|
||||
const muteBtn = $('#modal-mute-btn');
|
||||
const isMuted = state.mutedUsers.has(state.currentModalUserId);
|
||||
muteBtn.textContent = isMuted ? '🔇 User Muted' : '🔊 Mute User';
|
||||
muteBtn.className = isMuted ? 'control-btn muted' : 'control-btn';
|
||||
}
|
||||
static resetUserVolume() {
|
||||
if (!state.currentModalUserId) return;
|
||||
const volumeSlider = document.getElementById('user-volume-slider');
|
||||
const volumePercentage = document.getElementById('volume-percentage');
|
||||
const volumeSlider = $('#user-volume-slider');
|
||||
const volumePercentage = $('#volume-percentage');
|
||||
volumeSlider.value = 100;
|
||||
volumePercentage.textContent = '100%';
|
||||
ModalManager.updateUserVolume();
|
||||
@ -1847,7 +1844,7 @@ class ModalManager {
|
||||
// ==================== VOICE CHAT MANAGER ====================
|
||||
class VoiceChatManager {
|
||||
static async joinVoiceChat() {
|
||||
const usernameInput = document.getElementById('username-input');
|
||||
const usernameInput = $('#username-input');
|
||||
const username = usernameInput.value.trim();
|
||||
state.intentionalDisconnect = false;
|
||||
if (!username) {
|
||||
@ -1892,7 +1889,7 @@ class VoiceChatManager {
|
||||
PeerConnectionManager.stopPeerHealthCheck();
|
||||
PeerConnectionManager.cleanupAllConnections();
|
||||
UserManager.onVoiceChatLeave();
|
||||
document.getElementById('audio-container').innerHTML = '';
|
||||
$('#audio-container').innerHTML = '';
|
||||
state.reset();
|
||||
ModalManager.closeUserModal();
|
||||
state.intentionalDisconnect = true;
|
||||
@ -1920,7 +1917,7 @@ class VoiceChatManager {
|
||||
state.isInVoiceChat = false;
|
||||
UIManager.updateJoinButton('Join Voice Chat', false);
|
||||
UIManager.showUsernameUI();
|
||||
const usernameInput = document.getElementById('username-input');
|
||||
const usernameInput = $('#username-input');
|
||||
usernameInput.focus();
|
||||
usernameInput.select();
|
||||
console.log('Username rejected, reset to initial state');
|
||||
@ -1929,11 +1926,23 @@ class VoiceChatManager {
|
||||
// ==================== EVENT HANDLERS ====================
|
||||
class EventHandlers {
|
||||
static setupEventListeners() {
|
||||
const usernameInput = document.getElementById('username-input');
|
||||
const joinChatBtn = document.getElementById('join-chat-btn');
|
||||
const chatInput = document.getElementById('chat-input');
|
||||
const sendBtn = document.getElementById('send-btn');
|
||||
const fileBtn = document.getElementById('file-btn');
|
||||
const usernameInput = $('#username-input');
|
||||
const joinChatBtn = $('#join-chat-btn');
|
||||
const chatInput = $('#chat-input');
|
||||
const sendBtn = $('#send-btn');
|
||||
const chatMessages = $('.chat-messages');
|
||||
// const fileBtn = $('#file-btn');
|
||||
|
||||
|
||||
chatMessages.addEventListener('scroll', function() {
|
||||
const atBottom = UIManager.isChatScrolledToBottom();
|
||||
if (!atBottom) {
|
||||
$('#scroll-btn').style.display = 'block';
|
||||
}
|
||||
if (atBottom) {
|
||||
$('#scroll-btn').style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
joinChatBtn.disabled = usernameInput.value.trim().length === 0;
|
||||
|
||||
@ -1946,12 +1955,13 @@ class EventHandlers {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
chatInput.addEventListener('input', function(e) {
|
||||
sendBtn.disabled = this.value.trim().length === 0;
|
||||
const textarea = e.target;
|
||||
textarea.style.height = 'auto';
|
||||
textarea.style.height = Math.min(textarea.scrollHeight, window.innerHeight * 0.5) + 'px';
|
||||
document.getElementById('send-btn').disabled = textarea.value.trim().length === 0;
|
||||
$('#send-btn').disabled = textarea.value.trim().length === 0;
|
||||
});
|
||||
|
||||
chatInput.addEventListener('keydown', function(e) {
|
||||
@ -1965,7 +1975,7 @@ class EventHandlers {
|
||||
}
|
||||
static setupGlobalEventListeners() {
|
||||
document.addEventListener('click', function(event) {
|
||||
const modal = document.getElementById('user-control-modal');
|
||||
const modal = $('#user-control-modal');
|
||||
if (event.target === modal) {
|
||||
ModalManager.closeUserModal();
|
||||
}
|
||||
@ -1998,7 +2008,7 @@ class EventHandlers {
|
||||
}
|
||||
|
||||
static sendChatMessage() {
|
||||
const chatInput = document.getElementById('chat-input');
|
||||
const chatInput = $('#chat-input');
|
||||
const message = chatInput.value.trim();
|
||||
if (!message || !state.ws || state.ws.readyState !== WebSocket.OPEN) {
|
||||
return;
|
||||
@ -2006,7 +2016,7 @@ class EventHandlers {
|
||||
WebSocketManager.sendChatMessage(message);
|
||||
chatInput.value = '';
|
||||
chatInput.style.height = 'auto';
|
||||
document.getElementById('send-btn').disabled = true;
|
||||
$('#send-btn').disabled = true;
|
||||
}
|
||||
}
|
||||
// ==================== DEBUG UTILITIES ====================
|
||||
@ -2115,31 +2125,20 @@ class DebugUtils {
|
||||
// }
|
||||
// }, 5000);
|
||||
|
||||
|
||||
$('.chat-messages').addEventListener('scroll', function() {
|
||||
const atBottom = UIManager.isChatScrolledToBottom();
|
||||
if (!atBottom) {
|
||||
$('#scroll-btn').style.display = 'block';
|
||||
}
|
||||
if (atBottom) {
|
||||
$('#scroll-btn').style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// ==================== INITIALIZATION ====================
|
||||
for (let { event, target } of [
|
||||
{ event: 'DOMContentLoaded', target: document },
|
||||
{ event: 'online', target: window }
|
||||
]) {
|
||||
// Auto-join on load
|
||||
target.addEventListener(event, async function() {
|
||||
state.load();
|
||||
if (state.currentUsername) {
|
||||
document.getElementById('username-input').value = state.currentUsername;
|
||||
$('#username-input').value = state.currentUsername;
|
||||
}
|
||||
EventHandlers.setupEventListeners();
|
||||
await AudioManager.requestMicrophonePermission();
|
||||
VoiceChatManager.joinVoiceChat();
|
||||
await VoiceChatManager.joinVoiceChat();
|
||||
});
|
||||
}
|
||||
// ================== DE-INITIALIZATION ===================
|
||||
|
Loading…
x
Reference in New Issue
Block a user