Compare commits
7 Commits
a434f11561
...
191a368258
| Author | SHA1 | Date | |
|---|---|---|---|
| 191a368258 | |||
| 7a10206617 | |||
| 8b96f4dc8a | |||
| 4666986f78 | |||
| 5e002004cc | |||
| d3fb0eacb6 | |||
| 7bcb670b96 |
@@ -89,8 +89,9 @@
|
||||
border-radius: 8px;
|
||||
opacity: 0.95;
|
||||
display: none;
|
||||
z-index: 1000;
|
||||
z-index: 3000;
|
||||
font-size: 0.9rem;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.server-card {
|
||||
@@ -241,69 +242,6 @@
|
||||
}
|
||||
|
||||
/* Conversation View Styles */
|
||||
.conversation-view {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.conversations-list {
|
||||
max-height: 600px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #444;
|
||||
border-radius: 8px;
|
||||
padding: 1rem;
|
||||
background: #222;
|
||||
}
|
||||
|
||||
.conversation-message {
|
||||
margin-bottom: 1rem;
|
||||
padding: 0.75rem;
|
||||
border-radius: 8px;
|
||||
border-left: 4px solid;
|
||||
}
|
||||
|
||||
.conversation-message.user-message {
|
||||
background: #2a2a3a;
|
||||
border-left-color: #4CAF50;
|
||||
}
|
||||
|
||||
.conversation-message.bot-message {
|
||||
background: #3a2a2a;
|
||||
border-left-color: #2196F3;
|
||||
}
|
||||
|
||||
.message-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.sender {
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.timestamp {
|
||||
color: #999;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.message-content {
|
||||
color: #ddd;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.message-attachments {
|
||||
margin-top: 0.5rem;
|
||||
padding: 0.5rem;
|
||||
background: rgba(255,255,255,0.05);
|
||||
border-radius: 4px;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
.message-reactions {
|
||||
margin-top: 0.5rem;
|
||||
display: flex;
|
||||
@@ -1908,21 +1846,59 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
}, { passive: false });
|
||||
}
|
||||
|
||||
// Set up periodic updates
|
||||
setInterval(loadStatus, 10000);
|
||||
setInterval(loadLogs, 5000);
|
||||
setInterval(loadActiveArguments, 5000); // Refresh active arguments
|
||||
// Set up periodic updates with visibility-aware polling
|
||||
let statusInterval, logsInterval, argsInterval;
|
||||
|
||||
function startPolling() {
|
||||
if (!statusInterval) statusInterval = setInterval(loadStatus, 10000);
|
||||
if (!logsInterval) logsInterval = setInterval(loadLogs, 5000);
|
||||
if (!argsInterval) argsInterval = setInterval(loadActiveArguments, 5000);
|
||||
}
|
||||
|
||||
function stopPolling() {
|
||||
clearInterval(statusInterval); statusInterval = null;
|
||||
clearInterval(logsInterval); logsInterval = null;
|
||||
clearInterval(argsInterval); argsInterval = null;
|
||||
}
|
||||
|
||||
document.addEventListener('visibilitychange', () => {
|
||||
if (document.hidden) {
|
||||
stopPolling();
|
||||
console.log('⏸ Tab hidden — polling paused');
|
||||
} else {
|
||||
loadStatus(); loadLogs(); loadActiveArguments();
|
||||
startPolling();
|
||||
console.log('▶️ Tab visible — polling resumed');
|
||||
}
|
||||
});
|
||||
|
||||
startPolling();
|
||||
});
|
||||
|
||||
// Utility functions
|
||||
let notificationTimer = null;
|
||||
|
||||
function showNotification(message, type = 'info') {
|
||||
const notification = document.getElementById('notification');
|
||||
notification.textContent = message;
|
||||
notification.style.display = 'block';
|
||||
notification.style.backgroundColor = type === 'error' ? '#d32f2f' : '#222';
|
||||
notification.style.opacity = '0.95';
|
||||
|
||||
setTimeout(() => {
|
||||
notification.style.display = 'none';
|
||||
if (type === 'error') {
|
||||
notification.style.backgroundColor = '#d32f2f';
|
||||
} else if (type === 'success') {
|
||||
notification.style.backgroundColor = '#2e7d32';
|
||||
} else {
|
||||
notification.style.backgroundColor = '#222';
|
||||
}
|
||||
|
||||
if (notificationTimer) clearTimeout(notificationTimer);
|
||||
notificationTimer = setTimeout(() => {
|
||||
notification.style.opacity = '0';
|
||||
setTimeout(() => {
|
||||
notification.style.display = 'none';
|
||||
notificationTimer = null;
|
||||
}, 300);
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
@@ -2521,12 +2497,15 @@ async function updateBedtimeRange(guildId) {
|
||||
const [startHour, startMinute] = startTime.split(':').map(Number);
|
||||
const [endHour, endMinute] = endTime.split(':').map(Number);
|
||||
|
||||
const button = document.querySelector(`button[onclick="updateBedtimeRange('${guildIdStr}')"]`);
|
||||
const originalText = button ? button.textContent : 'Update Bedtime Range';
|
||||
|
||||
try {
|
||||
// Show loading state
|
||||
const button = document.querySelector(`button[onclick="updateBedtimeRange('${guildIdStr}')"]`);
|
||||
const originalText = button.textContent;
|
||||
button.textContent = 'Updating...';
|
||||
button.disabled = true;
|
||||
if (button) {
|
||||
button.textContent = 'Updating...';
|
||||
button.disabled = true;
|
||||
}
|
||||
|
||||
// Send the update request
|
||||
const response = await fetch(`/servers/${guildIdStr}/bedtime-range`, {
|
||||
@@ -2556,9 +2535,8 @@ async function updateBedtimeRange(guildId) {
|
||||
} catch (error) {
|
||||
console.error('Failed to update bedtime range:', error);
|
||||
showNotification(error.message || 'Failed to update bedtime range', 'error');
|
||||
|
||||
} finally {
|
||||
// Restore button state
|
||||
const button = document.querySelector(`button[onclick="updateBedtimeRange('${guildIdStr}')"]`);
|
||||
if (button) {
|
||||
button.textContent = originalText;
|
||||
button.disabled = false;
|
||||
@@ -4064,6 +4042,7 @@ function scrollLogsToBottom() {
|
||||
}
|
||||
|
||||
function escapeHtml(text) {
|
||||
if (!text) return '';
|
||||
const div = document.createElement('div');
|
||||
div.textContent = text;
|
||||
return div.innerHTML;
|
||||
@@ -5045,12 +5024,15 @@ function addChatMessage(sender, content, isError = false) {
|
||||
|
||||
messageDiv.innerHTML = `
|
||||
<div class="chat-message-header">
|
||||
<span class="chat-message-sender">${sender}</span>
|
||||
<span class="chat-message-sender">${escapeHtml(sender)}</span>
|
||||
<span class="chat-message-time">${timestamp}</span>
|
||||
</div>
|
||||
<div class="chat-message-content">${content}</div>
|
||||
<div class="chat-message-content"></div>
|
||||
`;
|
||||
|
||||
// Set content via textContent to prevent XSS
|
||||
messageDiv.querySelector('.chat-message-content').textContent = content;
|
||||
|
||||
chatMessages.appendChild(messageDiv);
|
||||
|
||||
// Scroll to bottom
|
||||
@@ -5863,6 +5845,37 @@ function closeCreateMemoryModal() {
|
||||
document.getElementById('create-memory-modal').style.display = 'none';
|
||||
}
|
||||
|
||||
// Modal keyboard and backdrop close handlers
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') {
|
||||
const editModal = document.getElementById('edit-memory-modal');
|
||||
const createModal = document.getElementById('create-memory-modal');
|
||||
if (editModal && editModal.style.display !== 'none') closeEditMemoryModal();
|
||||
if (createModal && createModal.style.display !== 'none') closeCreateMemoryModal();
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
const editModal = document.getElementById('edit-memory-modal');
|
||||
const createModal = document.getElementById('create-memory-modal');
|
||||
if (editModal) {
|
||||
editModal.setAttribute('role', 'dialog');
|
||||
editModal.setAttribute('aria-modal', 'true');
|
||||
editModal.setAttribute('aria-label', 'Edit Memory');
|
||||
editModal.addEventListener('click', function(e) {
|
||||
if (e.target === this) closeEditMemoryModal();
|
||||
});
|
||||
}
|
||||
if (createModal) {
|
||||
createModal.setAttribute('role', 'dialog');
|
||||
createModal.setAttribute('aria-modal', 'true');
|
||||
createModal.setAttribute('aria-label', 'Create Memory');
|
||||
createModal.addEventListener('click', function(e) {
|
||||
if (e.target === this) closeCreateMemoryModal();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
async function saveNewMemory() {
|
||||
const collection = document.getElementById('create-memory-collection').value;
|
||||
const content = document.getElementById('create-memory-content').value.trim();
|
||||
@@ -5930,13 +5943,6 @@ function filterMemories(listId, searchTerm) {
|
||||
});
|
||||
}
|
||||
|
||||
function escapeHtml(str) {
|
||||
if (!str) return '';
|
||||
const div = document.createElement('div');
|
||||
div.textContent = str;
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
function escapeJsonForAttribute(obj) {
|
||||
// Properly escape JSON for use in HTML attributes
|
||||
return JSON.stringify(obj)
|
||||
|
||||
Reference in New Issue
Block a user