Spaces:
Sleeping
Sleeping
// Main JavaScript utilities and helpers | |
// Global variables | |
window.currentUser = null; | |
window.currentConversation = null; | |
// Utility functions | |
function formatTime(timestamp) { | |
const date = new Date(timestamp); | |
const now = new Date(); | |
const diff = now - date; | |
if (diff < 60000) { // Less than 1 minute | |
return 'now'; | |
} else if (diff < 3600000) { // Less than 1 hour | |
return Math.floor(diff / 60000) + 'm'; | |
} else if (diff < 86400000) { // Less than 1 day | |
return Math.floor(diff / 3600000) + 'h'; | |
} else { | |
return date.toLocaleDateString(); | |
} | |
} | |
function formatMessageTime(timestamp) { | |
const date = new Date(timestamp); | |
return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); | |
} | |
function escapeHtml(unsafe) { | |
return unsafe | |
.replace(/&/g, "&") | |
.replace(/</g, "<") | |
.replace(/>/g, ">") | |
.replace(/"/g, """) | |
.replace(/'/g, "'"); | |
} | |
function showToast(message, type = 'info') { | |
// Create toast element | |
const toast = document.createElement('div'); | |
toast.className = `toast align-items-center text-white bg-${type === 'error' ? 'danger' : 'success'} border-0`; | |
toast.setAttribute('role', 'alert'); | |
toast.innerHTML = ` | |
<div class="d-flex"> | |
<div class="toast-body"> | |
${escapeHtml(message)} | |
</div> | |
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button> | |
</div> | |
`; | |
// Add to page | |
let toastContainer = document.querySelector('.toast-container'); | |
if (!toastContainer) { | |
toastContainer = document.createElement('div'); | |
toastContainer.className = 'toast-container position-fixed top-0 end-0 p-3'; | |
document.body.appendChild(toastContainer); | |
} | |
toastContainer.appendChild(toast); | |
// Show toast | |
const bsToast = new bootstrap.Toast(toast); | |
bsToast.show(); | |
// Remove from DOM after hidden | |
toast.addEventListener('hidden.bs.toast', () => { | |
toast.remove(); | |
}); | |
} | |
function showError(message) { | |
showToast(message, 'error'); | |
} | |
function showSuccess(message) { | |
showToast(message, 'success'); | |
} | |
// API helper functions | |
async function apiRequest(url, options = {}) { | |
try { | |
const response = await fetch(url, { | |
...options, | |
headers: { | |
'Content-Type': 'application/json', | |
...options.headers | |
} | |
}); | |
if (!response.ok) { | |
throw new Error(`HTTP error! status: ${response.status}`); | |
} | |
return await response.json(); | |
} catch (error) { | |
console.error('API request failed:', error); | |
throw error; | |
} | |
} | |
// Online status management | |
let statusUpdateInterval; | |
function startStatusUpdates() { | |
// Update online status every 30 seconds | |
statusUpdateInterval = setInterval(updateOnlineStatus, 30000); | |
// Update on page visibility change | |
document.addEventListener('visibilitychange', () => { | |
if (!document.hidden) { | |
updateOnlineStatus(); | |
} | |
}); | |
// Update on page unload | |
window.addEventListener('beforeunload', () => { | |
updateOnlineStatus(false); | |
}); | |
// Initial update | |
updateOnlineStatus(); | |
} | |
async function updateOnlineStatus(online = true) { | |
try { | |
await apiRequest('/api/update_status', { | |
method: 'POST', | |
body: JSON.stringify({ online }) | |
}); | |
} catch (error) { | |
console.error('Failed to update online status:', error); | |
} | |
} | |
function stopStatusUpdates() { | |
if (statusUpdateInterval) { | |
clearInterval(statusUpdateInterval); | |
statusUpdateInterval = null; | |
} | |
} | |
// Initialize common functionality | |
document.addEventListener('DOMContentLoaded', () => { | |
// Start status updates if on chat page | |
if (document.body.classList.contains('chat-page')) { | |
startStatusUpdates(); | |
// Handle mobile keyboard viewport changes | |
if (/Mobi|Android/i.test(navigator.userAgent)) { | |
handleMobileViewport(); | |
} | |
} | |
// Handle page unload | |
window.addEventListener('beforeunload', () => { | |
stopStatusUpdates(); | |
}); | |
}); | |
// Handle mobile viewport changes when keyboard appears/disappears | |
function handleMobileViewport() { | |
let initialViewportHeight = window.innerHeight; | |
window.addEventListener('resize', () => { | |
const currentHeight = window.innerHeight; | |
const chatMessages = document.getElementById('chatMessages'); | |
if (chatMessages) { | |
// If keyboard is shown (viewport shrunk significantly) | |
if (currentHeight < initialViewportHeight * 0.75) { | |
// Scroll to bottom when keyboard appears | |
setTimeout(() => { | |
chatMessages.scrollTop = chatMessages.scrollHeight; | |
}, 300); | |
} | |
} | |
}); | |
// Handle visual viewport API if available | |
if (window.visualViewport) { | |
window.visualViewport.addEventListener('resize', () => { | |
const chatMessages = document.getElementById('chatMessages'); | |
if (chatMessages) { | |
setTimeout(() => { | |
chatMessages.scrollTop = chatMessages.scrollHeight; | |
}, 100); | |
} | |
}); | |
} | |
} | |
// Export functions for use in other scripts | |
window.MainJS = { | |
formatTime, | |
formatMessageTime, | |
escapeHtml, | |
showToast, | |
showError, | |
showSuccess, | |
apiRequest, | |
updateOnlineStatus | |
}; | |