new file: .gitignore
new file: Dockerfile new file: README.md new file: app.py new file: chat-logs/chat-index.json new file: chat-logs/crea-1-10.08.2020-merged.txt new file: chat-logs/crea-1-11.08.2020-merged.txt new file: chat-logs/crea-1-12.08.2020-merged.txt new file: chat-logs/crea-1-13.08.2020-merged.txt new file: chat-logs/crea-1-14.08.2020-merged.txt new file: chat-logs/crea-1-15.08.2020-merged.txt new file: chat-logs/crea-1-18.08.2020-merged.txt new file: chat-logs/crea-1-20.08.2020-merged.txt new file: chat-logs/crea-1-2020-07-27-1-filtered.txt new file: chat-logs/crea-1-2020-07-28-1-filtered.txt new file: chat-logs/crea-1-2020-07-29-1-filtered.txt new file: chat-logs/crea-1-2020-07-30-1-filtered.txt new file: chat-logs/crea-1-2020-08-03-1-filtered.txt new file: chat-logs/crea-1-2020-08-04-1-filtered.txt new file: chat-logs/crea-1-2020-08-08-1-filtered.txt new file: chat-logs/crea-1-2020-08-09-1-filtered.txt new file: chat-logs/crea-1-2020-08-10-1-filtered.txt new file: chat-logs/crea-1-2020-08-11-1-filtered.txt new file: chat-logs/crea-1-2020-08-13-1-filtered.txt new file: chat-logs/crea-1-2020-08-16-1-filtered.txt new file: chat-logs/crea-1-2020-08-17-1-filtered.txt new file: chat-logs/crea-1-2020-08-18-1-filtered.txt new file: chat-logs/crea-1-2020-08-20-1-filtered.txt new file: chat-logs/crea-1-2020-08-24-1-filtered.txt new file: chat-logs/crea-1-2020-08-29-1-filtered.txt new file: chat-logs/crea-1-2020-08-30-1-filtered.txt new file: chat-logs/crea-1-21.08.2020-merged.txt new file: chat-logs/crea-1-22.08.2020-merged.txt new file: chat-logs/crea-1-23.08.2020-merged.txt new file: chat-logs/crea-1-24.07.2020-merged.txt new file: chat-logs/crea-1-25.07.2020-merged.txt new file: chat-logs/crea-1-25.08.2020-merged.txt new file: chat-logs/crea-1-26.07.2020-merged.txt new file: chat-logs/crea-1-26.08.2020-merged.txt new file: chat-logs/crea-1-27.08.2020-merged.txt new file: chat-logs/crea-1-28.08.2020-merged.txt new file: chat-logs/crea-1-crea-1-10.08.2020-merged-filtered.txt new file: chat-logs/crea-1-crea-1-11.08.2020-merged-filtered.txt new file: chat-logs/crea-1-crea-1-12.08.2020-merged-filtered.txt new file: chat-logs/crea-1-crea-1-14.08.2020-merged-filtered.txt new file: chat-logs/crea-1-crea-1-15.08.2020-merged-filtered.txt new file: chat-logs/crea-1-crea-1-18.08.2020-merged-filtered.txt new file: chat-logs/crea-1-crea-1-20.08.2020-merged-filtered.txt new file: chat-logs/crea-1-crea-1-21.08.2020-merged-filtered.txt new file: chat-logs/crea-1-crea-1-22.08.2020-merged-filtered.txt new file: chat-logs/crea-1-crea-1-23.08.2020-merged-filtered.txt new file: chat-logs/crea-1-crea-1-24.07.2020-merged-filtered.txt new file: chat-logs/crea-1-crea-1-25.07.2020-merged-filtered.txt new file: chat-logs/crea-1-crea-1-25.08.2020-merged-filtered.txt new file: chat-logs/crea-1-crea-1-26.07.2020-merged-filtered.txt new file: chat-logs/crea-1-crea-1-26.08.2020-merged-filtered.txt new file: chat-logs/crea-1-crea-1-27.08.2020-merged-filtered.txt new file: chat-logs/crea-1-crea-1-28.08.2020-merged-filtered.txt new file: chat-logs/survival-1-15.08.2020-merged.txt new file: chat-logs/survival-1-2020-07-27-1-filtered.txt new file: chat-logs/survival-1-2020-07-28-1-filtered.txt new file: chat-logs/survival-1-2020-08-07-1-filtered.txt new file: chat-logs/survival-1-2020-08-08-1-filtered.txt new file: chat-logs/survival-1-2020-08-11-1-filtered.txt new file: chat-logs/survival-1-2020-08-13-1-filtered.txt new file: chat-logs/survival-1-2020-08-14-1-filtered.txt new file: chat-logs/survival-1-2020-08-17-1-filtered.txt new file: chat-logs/survival-1-2020-08-18-1-filtered.txt new file: chat-logs/survival-1-2020-08-19-1-filtered.txt new file: chat-logs/survival-1-25.07.2020-merged.txt new file: chat-logs/survival-1-survival-1-15.08.2020-merged-filtered.txt new file: chat-logs/survival-1-survival-1-25.07.2020-merged-filtered.txt new file: chat-logs/thesur-1-2020-08-17-1-filtered.txt new file: chat-logs/thesur-1-2020-08-31-1-filtered.txt new file: count_all_sessions.py new file: count_sessions.py new file: index.html new file: local-chat-analyzer.js new file: merge_daily_logs.py new file: process_thesur_logs.py new file: quick_add.py new file: requirements.txt new file: script.js new file: server.py new file: statistics-integration.js new file: statistics.css new file: statistics.js new file: style.css
This commit is contained in:
550
statistics-integration.js
Normal file
550
statistics-integration.js
Normal file
@@ -0,0 +1,550 @@
|
||||
/* Statistics Integration */
|
||||
// This file extends the existing functionality without modifying original files
|
||||
|
||||
(function() {
|
||||
let statsButtonAdded = false;
|
||||
let globalStatsButtonAdded = false;
|
||||
|
||||
function addStatsButton() {
|
||||
if (statsButtonAdded) return;
|
||||
|
||||
console.log('Attempting to add stats button...');
|
||||
|
||||
// Find the control groups
|
||||
const controlGroups = document.querySelectorAll('.control-group');
|
||||
console.log('Found control groups:', controlGroups.length);
|
||||
|
||||
if (controlGroups.length >= 2) {
|
||||
const downloadControlGroup = controlGroups[1]; // Second control group with download buttons
|
||||
|
||||
const statsButton = document.createElement('button');
|
||||
statsButton.id = 'showStats';
|
||||
statsButton.className = 'btn-secondary';
|
||||
statsButton.innerHTML = '📊 Statistics';
|
||||
statsButton.addEventListener('click', () => {
|
||||
console.log('Stats button clicked');
|
||||
|
||||
// Use the new local chat analyzer
|
||||
if (window.localChatAnalyzer) {
|
||||
window.localChatAnalyzer.analyzeCurrentChat();
|
||||
} else {
|
||||
// Fallback to original method
|
||||
console.log('window.chatStats available:', !!window.chatStats);
|
||||
|
||||
if (window.chatStats) {
|
||||
console.log('Current data available:', !!window.chatStats.currentData);
|
||||
if (window.chatStats.currentData) {
|
||||
window.chatStats.showStats();
|
||||
} else {
|
||||
console.log('No statistics data available yet, triggering analysis...');
|
||||
triggerStatsAnalysis();
|
||||
setTimeout(() => {
|
||||
if (window.chatStats.currentData) {
|
||||
window.chatStats.showStats();
|
||||
} else {
|
||||
alert('No chat data available for statistics');
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
} else {
|
||||
console.error('chatStats module not loaded');
|
||||
alert('Statistics module not loaded');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Insert before the download map button or at the end
|
||||
const downloadMapButton = document.getElementById('downloadMap');
|
||||
if (downloadMapButton) {
|
||||
downloadControlGroup.insertBefore(statsButton, downloadMapButton);
|
||||
} else {
|
||||
downloadControlGroup.appendChild(statsButton);
|
||||
}
|
||||
|
||||
statsButtonAdded = true;
|
||||
console.log('Stats button added successfully');
|
||||
} else {
|
||||
console.log('Control groups not found yet');
|
||||
}
|
||||
}
|
||||
|
||||
function addGlobalStatsButton() {
|
||||
if (globalStatsButtonAdded) return;
|
||||
|
||||
console.log('Adding global stats button...');
|
||||
|
||||
// Add button to header area
|
||||
const header = document.querySelector('header');
|
||||
if (header) {
|
||||
const globalStatsButton = document.createElement('button');
|
||||
globalStatsButton.id = 'globalStatsButton';
|
||||
globalStatsButton.className = 'btn-primary global-stats-btn';
|
||||
globalStatsButton.innerHTML = '📊 Global Chat Statistics';
|
||||
globalStatsButton.style.cssText = `
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
z-index: 1000;
|
||||
padding: 12px 20px;
|
||||
background: linear-gradient(135deg, #007acc, #40a9ff);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 4px 12px rgba(0, 122, 204, 0.3);
|
||||
transition: all 0.3s ease;
|
||||
font-size: 14px;
|
||||
`;
|
||||
|
||||
globalStatsButton.addEventListener('mouseenter', () => {
|
||||
globalStatsButton.style.transform = 'translateY(-2px)';
|
||||
globalStatsButton.style.boxShadow = '0 6px 16px rgba(0, 122, 204, 0.4)';
|
||||
});
|
||||
|
||||
globalStatsButton.addEventListener('mouseleave', () => {
|
||||
globalStatsButton.style.transform = 'translateY(0)';
|
||||
globalStatsButton.style.boxShadow = '0 4px 12px rgba(0, 122, 204, 0.3)';
|
||||
});
|
||||
|
||||
globalStatsButton.addEventListener('click', () => {
|
||||
console.log('Global stats button clicked');
|
||||
showGlobalStatistics();
|
||||
});
|
||||
|
||||
document.body.appendChild(globalStatsButton);
|
||||
globalStatsButtonAdded = true;
|
||||
console.log('Global stats button added successfully');
|
||||
}
|
||||
}
|
||||
|
||||
async function showGlobalStatistics() {
|
||||
console.log('Loading global statistics...');
|
||||
|
||||
try {
|
||||
// Create modal
|
||||
const modal = createGlobalStatsModal();
|
||||
document.body.appendChild(modal);
|
||||
|
||||
// Load chat index
|
||||
const response = await fetch('chat-logs/chat-index.json');
|
||||
const chatIndex = await response.json();
|
||||
|
||||
// Calculate global stats
|
||||
const globalStats = calculateGlobalStats(chatIndex);
|
||||
|
||||
// Display stats
|
||||
displayGlobalStats(globalStats, chatIndex);
|
||||
|
||||
// Show modal
|
||||
modal.style.display = 'flex';
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error loading global statistics:', error);
|
||||
alert('Error loading global statistics: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
function createGlobalStatsModal() {
|
||||
const modal = document.createElement('div');
|
||||
modal.id = 'globalStatsModal';
|
||||
modal.style.cssText = `
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
z-index: 2000;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
modal.innerHTML = `
|
||||
<div class="global-stats-content" style="
|
||||
background: #1e1e1e;
|
||||
color: white;
|
||||
border-radius: 12px;
|
||||
width: 90%;
|
||||
max-width: 1000px;
|
||||
max-height: 80%;
|
||||
overflow-y: auto;
|
||||
padding: 0;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
|
||||
">
|
||||
<div class="global-stats-header" style="
|
||||
padding: 20px;
|
||||
border-bottom: 1px solid #333;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
background: #2d2d2d;
|
||||
border-radius: 12px 12px 0 0;
|
||||
">
|
||||
<h2 style="margin: 0; color: #007acc;">📊 Global Chat Statistics</h2>
|
||||
<button id="closeGlobalStats" style="
|
||||
background: none;
|
||||
border: none;
|
||||
color: white;
|
||||
font-size: 24px;
|
||||
cursor: pointer;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
">×</button>
|
||||
</div>
|
||||
<div id="globalStatsBody" style="padding: 20px;">
|
||||
<div style="text-align: center; padding: 40px;">
|
||||
<div style="font-size: 48px; margin-bottom: 20px;">📊</div>
|
||||
<div>Loading global statistics...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Close button
|
||||
modal.addEventListener('click', (e) => {
|
||||
if (e.target === modal) {
|
||||
modal.remove();
|
||||
}
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
const closeBtn = modal.querySelector('#closeGlobalStats');
|
||||
if (closeBtn) {
|
||||
closeBtn.addEventListener('click', () => modal.remove());
|
||||
}
|
||||
}, 100);
|
||||
|
||||
return modal;
|
||||
}
|
||||
|
||||
function calculateGlobalStats(chatIndex) {
|
||||
const stats = {
|
||||
totalChats: chatIndex.chats.length,
|
||||
totalCategories: Object.keys(chatIndex.categories).length,
|
||||
categories: {},
|
||||
dateRange: { earliest: null, latest: null },
|
||||
totalEstimatedMessages: 0,
|
||||
averageMessagesPerChat: 0
|
||||
};
|
||||
|
||||
// Calculate category stats
|
||||
Object.keys(chatIndex.categories).forEach(categoryKey => {
|
||||
const categoryInfo = chatIndex.categories[categoryKey];
|
||||
const categoryChats = chatIndex.chats.filter(chat => chat.category === categoryKey);
|
||||
|
||||
stats.categories[categoryKey] = {
|
||||
name: categoryInfo.name,
|
||||
color: categoryInfo.color,
|
||||
chatCount: categoryChats.length,
|
||||
percentage: Math.round((categoryChats.length / stats.totalChats) * 100),
|
||||
estimatedMessages: categoryChats.reduce((sum, chat) => sum + (chat.messages || 0), 0)
|
||||
};
|
||||
});
|
||||
|
||||
// Calculate date range and messages
|
||||
chatIndex.chats.forEach(chat => {
|
||||
const chatDate = new Date(chat.date);
|
||||
if (!stats.dateRange.earliest || chatDate < stats.dateRange.earliest) {
|
||||
stats.dateRange.earliest = chatDate;
|
||||
}
|
||||
if (!stats.dateRange.latest || chatDate > stats.dateRange.latest) {
|
||||
stats.dateRange.latest = chatDate;
|
||||
}
|
||||
|
||||
stats.totalEstimatedMessages += chat.messages || 0;
|
||||
});
|
||||
|
||||
stats.averageMessagesPerChat = Math.round(stats.totalEstimatedMessages / stats.totalChats);
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
function displayGlobalStats(stats, chatIndex) {
|
||||
const body = document.getElementById('globalStatsBody');
|
||||
if (!body) return;
|
||||
|
||||
const categoriesArray = Object.entries(stats.categories)
|
||||
.sort((a, b) => b[1].chatCount - a[1].chatCount);
|
||||
|
||||
body.innerHTML = `
|
||||
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin-bottom: 30px;">
|
||||
<div class="stat-card" style="
|
||||
background: #2d2d2d;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #444;
|
||||
">
|
||||
<h3 style="color: #007acc; margin: 0 0 15px 0;">📈 Overview</h3>
|
||||
<div style="display: grid; gap: 10px;">
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<span>Total Chats:</span>
|
||||
<strong style="color: #40a9ff;">${stats.totalChats.toLocaleString()}</strong>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<span>Categories:</span>
|
||||
<strong style="color: #40a9ff;">${stats.totalCategories}</strong>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<span>Est. Messages:</span>
|
||||
<strong style="color: #40a9ff;">${stats.totalEstimatedMessages.toLocaleString()}</strong>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<span>Avg/Chat:</span>
|
||||
<strong style="color: #40a9ff;">${stats.averageMessagesPerChat}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stat-card" style="
|
||||
background: #2d2d2d;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #444;
|
||||
">
|
||||
<h3 style="color: #007acc; margin: 0 0 15px 0;">📅 Timeline</h3>
|
||||
<div style="display: grid; gap: 10px;">
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<span>First Chat:</span>
|
||||
<strong style="color: #40a9ff;">${stats.dateRange.earliest?.toLocaleDateString() || 'N/A'}</strong>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<span>Latest Chat:</span>
|
||||
<strong style="color: #40a9ff;">${stats.dateRange.latest?.toLocaleDateString() || 'N/A'}</strong>
|
||||
</div>
|
||||
<div style="display: flex; justify-content: space-between;">
|
||||
<span>Time Span:</span>
|
||||
<strong style="color: #40a9ff;">${calculateTimeSpan(stats.dateRange)}</strong>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stat-card" style="
|
||||
background: #2d2d2d;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #444;
|
||||
margin-bottom: 20px;
|
||||
">
|
||||
<h3 style="color: #007acc; margin: 0 0 20px 0;">📊 Category Breakdown</h3>
|
||||
<div style="display: grid; gap: 15px;">
|
||||
${categoriesArray.map(([key, category]) => `
|
||||
<div style="display: flex; align-items: center; gap: 15px;">
|
||||
<div style="
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: ${category.color};
|
||||
border-radius: 3px;
|
||||
flex-shrink: 0;
|
||||
"></div>
|
||||
<div style="min-width: 120px; font-weight: 500;">${category.name}</div>
|
||||
<div style="
|
||||
flex: 1;
|
||||
height: 20px;
|
||||
background: #1a1a1a;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
">
|
||||
<div style="
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, ${category.color}, ${category.color}aa);
|
||||
width: ${category.percentage}%;
|
||||
transition: width 0.5s ease;
|
||||
"></div>
|
||||
</div>
|
||||
<div style="min-width: 100px; text-align: right;">
|
||||
<strong style="color: #40a9ff;">${category.chatCount}</strong>
|
||||
<span style="color: #888; margin-left: 8px;">(${category.percentage}%)</span>
|
||||
</div>
|
||||
</div>
|
||||
`).join('')}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="
|
||||
background: #2d2d2d;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #444;
|
||||
text-align: center;
|
||||
color: #888;
|
||||
font-style: italic;
|
||||
">
|
||||
💡 Tip: Click on individual chat logs to see detailed statistics for that session
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function calculateTimeSpan(dateRange) {
|
||||
if (!dateRange.earliest || !dateRange.latest) return 'N/A';
|
||||
|
||||
const diffTime = Math.abs(dateRange.latest - dateRange.earliest);
|
||||
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
||||
|
||||
if (diffDays < 30) {
|
||||
return `${diffDays} days`;
|
||||
} else if (diffDays < 365) {
|
||||
const months = Math.round(diffDays / 30);
|
||||
return `${months} months`;
|
||||
} else {
|
||||
const years = Math.round(diffDays / 365);
|
||||
return `${years} years`;
|
||||
}
|
||||
}
|
||||
|
||||
function triggerStatsAnalysis() {
|
||||
if (!window.chatStats) {
|
||||
console.log('chatStats not available yet');
|
||||
return;
|
||||
}
|
||||
|
||||
// Try to get messages from the current chat viewer instance
|
||||
if (window.chatViewer && window.chatViewer.currentMessages) {
|
||||
console.log('Using chatViewer.currentMessages:', window.chatViewer.currentMessages.length);
|
||||
window.chatStats.analyzeChat(window.chatViewer.currentMessages);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback: Parse messages from DOM
|
||||
const chatMessages = document.querySelectorAll('.message');
|
||||
console.log('Found DOM messages:', chatMessages.length);
|
||||
|
||||
if (chatMessages.length > 0) {
|
||||
const messages = Array.from(chatMessages).map(msg => {
|
||||
const timestamp = msg.querySelector('.timestamp')?.textContent || '';
|
||||
const roleElement = msg.querySelector('.role-badge');
|
||||
const role = roleElement ? roleElement.textContent.toLowerCase() : 'member';
|
||||
const playerElement = msg.querySelector('.player-name');
|
||||
const messageElement = msg.querySelector('.message-text');
|
||||
|
||||
if (playerElement && messageElement) {
|
||||
return {
|
||||
type: 'chat',
|
||||
timestamp: timestamp.replace(/[\[\]]/g, ''),
|
||||
role: role,
|
||||
player: playerElement.textContent,
|
||||
message: messageElement.textContent
|
||||
};
|
||||
} else if (msg.classList.contains('join-leave')) {
|
||||
const text = msg.textContent;
|
||||
return {
|
||||
type: text.includes('joined') ? 'join' : 'leave',
|
||||
timestamp: timestamp.replace(/[\[\]]/g, ''),
|
||||
player: text.match(/(\w+) (joined|left)/)?.[1] || '',
|
||||
message: text
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}).filter(msg => msg !== null);
|
||||
|
||||
if (messages.length > 0) {
|
||||
console.log('Analyzing', messages.length, 'messages');
|
||||
window.chatStats.analyzeChat(messages);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for the page to load
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
console.log('DOM loaded, initializing statistics...');
|
||||
|
||||
// Add statistics CSS
|
||||
const link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
link.href = 'statistics.css';
|
||||
document.head.appendChild(link);
|
||||
|
||||
// Load local chat analyzer
|
||||
const analyzerScript = document.createElement('script');
|
||||
analyzerScript.src = 'local-chat-analyzer.js';
|
||||
analyzerScript.onload = () => {
|
||||
console.log('Local chat analyzer loaded');
|
||||
};
|
||||
document.head.appendChild(analyzerScript);
|
||||
|
||||
// Try to add button immediately
|
||||
setTimeout(addStatsButton, 100);
|
||||
|
||||
// Add global stats button (always available)
|
||||
setTimeout(addGlobalStatsButton, 200);
|
||||
|
||||
// Monitor for controls becoming visible
|
||||
const observer = new MutationObserver(function(mutations) {
|
||||
mutations.forEach(function(mutation) {
|
||||
// Check if controls became visible
|
||||
if (mutation.target.id === 'controls' && mutation.attributeName === 'style') {
|
||||
const controls = document.getElementById('controls');
|
||||
if (controls && controls.style.display !== 'none') {
|
||||
console.log('Controls became visible');
|
||||
setTimeout(addStatsButton, 100);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if chat content changed
|
||||
if (mutation.target.id === 'chatContent' && mutation.type === 'childList') {
|
||||
console.log('Chat content changed');
|
||||
setTimeout(() => {
|
||||
addStatsButton();
|
||||
triggerStatsAnalysis();
|
||||
}, 200);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Start observing
|
||||
const controls = document.getElementById('controls');
|
||||
const chatContainer = document.getElementById('chatContent');
|
||||
|
||||
if (controls) {
|
||||
observer.observe(controls, {
|
||||
attributes: true,
|
||||
attributeFilter: ['style']
|
||||
});
|
||||
}
|
||||
|
||||
if (chatContainer) {
|
||||
observer.observe(chatContainer, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
}
|
||||
|
||||
// Also check periodically for the first few seconds
|
||||
let checkCount = 0;
|
||||
const intervalCheck = setInterval(() => {
|
||||
checkCount++;
|
||||
addStatsButton();
|
||||
|
||||
// Check if there's already chat content
|
||||
const messages = document.querySelectorAll('.message');
|
||||
if (messages.length > 0) {
|
||||
triggerStatsAnalysis();
|
||||
}
|
||||
|
||||
if (checkCount >= 10 || statsButtonAdded) {
|
||||
clearInterval(intervalCheck);
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
// Ensure chatStats is available
|
||||
if (!window.chatStats) {
|
||||
console.log('Waiting for chatStats to be available...');
|
||||
const waitForStats = setInterval(() => {
|
||||
if (window.chatStats) {
|
||||
console.log('chatStats is now available');
|
||||
clearInterval(waitForStats);
|
||||
|
||||
// Trigger analysis if there are already messages
|
||||
const messages = document.querySelectorAll('.message');
|
||||
if (messages.length > 0) {
|
||||
console.log('Found existing messages, triggering analysis');
|
||||
triggerStatsAnalysis();
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
})();
|
||||
Reference in New Issue
Block a user