NEXT_MATCH fixed

parent 549596de
......@@ -1775,8 +1775,8 @@ class GamesThread(ThreadedComponent):
# Send MATCH_DONE message with result
self._send_match_done(fixture_id, match_id, result)
# Send START_INTRO message to start the next match cycle
self._dispatch_start_intro(fixture_id)
# Send NEXT_MATCH message to advance to next match
self._send_next_match(fixture_id, match_id)
except Exception as e:
logger.error(f"Failed to handle PLAY_VIDEO_RESULTS_DONE message: {e}")
......@@ -1818,12 +1818,8 @@ class GamesThread(ThreadedComponent):
finally:
session.close()
# Wait 2 seconds then send NEXT_MATCH
import time
time.sleep(2)
# Send NEXT_MATCH message
self._send_next_match(fixture_id, match_id)
# NEXT_MATCH is now sent immediately in _handle_play_video_result_done
# to avoid the 2-second delay and ensure proper sequencing
except Exception as e:
logger.error(f"Failed to handle MATCH_DONE message: {e}")
......
......@@ -243,16 +243,24 @@ class MatchTimerComponent(ThreadedComponent):
logger.info(f"Received NEXT_MATCH message for fixture {fixture_id}, match {match_id}")
logger.info("Previous match completed - restarting timer for next interval")
# Find and start the next match
# Start timer first to ensure countdown is visible immediately
match_interval = self._get_match_interval()
self._start_timer(match_interval * 60, fixture_id)
logger.info(f"Timer started for {match_interval} minute interval")
# Then find and start the next match
match_info = self._find_and_start_next_match()
if match_info:
logger.info(f"Started next match {match_info['match_id']} in fixture {match_info['fixture_id']}")
logger.info(f"Prepared next match {match_info['match_id']} in fixture {match_info['fixture_id']}")
# Reset timer for next interval
match_interval = self._get_match_interval()
self._start_timer(match_interval * 60, match_info['fixture_id'])
logger.info(f"Timer restarted for {match_interval} minute interval")
# Update timer with correct fixture_id if different
if match_info['fixture_id'] != fixture_id:
with self._timer_lock:
self.current_fixture_id = match_info['fixture_id']
# Send updated timer info
self._send_timer_update()
logger.info(f"Timer updated with fixture {match_info['fixture_id']}")
else:
logger.info("No more matches to start, stopping timer")
self._stop_timer()
......
......@@ -118,35 +118,41 @@ class OverlayWebChannel(QObject):
"""Send data update to JavaScript (thread-safe)"""
# Validate data before sending to prevent null emissions
if not data:
logger.warning("send_data_update called with null/empty data, skipping")
logger.warning("RESULTS DEBUG: send_data_update called with null/empty data, skipping")
return
# Debug original data before cleaning
logger.debug(f"OverlayWebChannel received data: {data}, type: {type(data)}")
logger.debug(f"OverlayWebChannel data keys: {list(data.keys()) if isinstance(data, dict) else 'not dict'}")
logger.info(f"RESULTS DEBUG: OverlayWebChannel received data: {data}, type: {type(data)}")
logger.info(f"RESULTS DEBUG: OverlayWebChannel data keys: {list(data.keys()) if isinstance(data, dict) else 'not dict'}")
# Check if this data contains results information
has_results_data = any(key in data for key in ['outcome', 'result', 'match', 'match_id', 'fixture_id'])
logger.info(f"RESULTS DEBUG: Data contains results info: {has_results_data}")
# Clean data to remove null/undefined values before sending to JavaScript
cleaned_data = self._clean_data(data)
logger.debug(f"OverlayWebChannel cleaned data: {cleaned_data}")
logger.info(f"RESULTS DEBUG: OverlayWebChannel cleaned data: {cleaned_data}")
if not cleaned_data:
logger.debug("All data properties were null/undefined, skipping JavaScript update")
logger.info("RESULTS DEBUG: All data properties were null/undefined, skipping JavaScript update")
return
# Debug what data is being sent to JavaScript
data_keys = list(cleaned_data.keys()) if isinstance(cleaned_data, dict) else []
logger.debug(f"OverlayWebChannel sending to JavaScript: {len(cleaned_data)} items with keys: {data_keys}")
logger.debug(f"Data type: {type(cleaned_data)}, Data is dict: {isinstance(cleaned_data, dict)}")
logger.info(f"RESULTS DEBUG: OverlayWebChannel sending to JavaScript: {len(cleaned_data)} items with keys: {data_keys}")
logger.info(f"RESULTS DEBUG: Data type: {type(cleaned_data)}, Data is dict: {isinstance(cleaned_data, dict)}")
with QMutexLocker(self.mutex):
self.overlay_data.update(cleaned_data)
logger.info(f"RESULTS DEBUG: Updated overlay_data, now contains: {list(self.overlay_data.keys())}")
# Add additional validation just before emit
if cleaned_data and isinstance(cleaned_data, dict) and any(v is not None for v in cleaned_data.values()):
logger.debug(f"OverlayWebChannel emitting dataUpdated signal with: {cleaned_data}")
logger.info(f"RESULTS DEBUG: OverlayWebChannel emitting dataUpdated signal with: {cleaned_data}")
self.dataUpdated.emit(cleaned_data)
data_keys = list(cleaned_data.keys()) if isinstance(cleaned_data, dict) else []
logger.debug(f"Signal emitted successfully with {len(cleaned_data)} data items: {data_keys}")
logger.info(f"RESULTS DEBUG: Signal emitted successfully with {len(cleaned_data)} data items: {data_keys}")
else:
logger.warning(f"Prevented emission of invalid data: {cleaned_data}")
logger.warning(f"RESULTS DEBUG: Prevented emission of invalid data: {cleaned_data}")
def _clean_data(self, data: Dict[str, Any]) -> Dict[str, Any]:
"""Clean data by removing null/undefined values before sending to JavaScript"""
......@@ -204,13 +210,19 @@ class OverlayWebChannel(QObject):
def getCurrentData(self) -> str:
"""Provide current overlay data to JavaScript via WebChannel"""
try:
logger.debug("OverlayWebChannel: getCurrentData called")
logger.info("RESULTS DEBUG: OverlayWebChannel getCurrentData called")
# Return current overlay data
current_data = dict(self.overlay_data)
logger.debug(f"OverlayWebChannel: Returning current data: {current_data}")
return json.dumps(current_data)
logger.info(f"RESULTS DEBUG: Current overlay_data keys: {list(current_data.keys())}")
logger.info(f"RESULTS DEBUG: Current overlay_data: {current_data}")
logger.info(f"RESULTS DEBUG: Returning current data to JavaScript: {current_data}")
json_result = json.dumps(current_data)
logger.info(f"RESULTS DEBUG: JSON result length: {len(json_result)}")
return json_result
except Exception as e:
logger.error(f"OverlayWebChannel: Failed to get current data: {e}")
logger.error(f"RESULTS DEBUG: OverlayWebChannel Failed to get current data: {e}")
import traceback
logger.error(f"RESULTS DEBUG: Full traceback: {traceback.format_exc()}")
return json.dumps({})
@pyqtSlot(result=str)
......
......@@ -634,25 +634,37 @@
// Handle timer updates from match_timer
const timerData = data.timer_update;
if (timerData.running && timerData.remaining_seconds !== undefined) {
// Format remaining time
const minutes = Math.floor(timerData.remaining_seconds / 60);
const seconds = timerData.remaining_seconds % 60;
const timeString = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
// Clear any existing countdown
if (countdownInterval) {
clearInterval(countdownInterval);
countdownInterval = null;
}
const countdownTimer = document.getElementById('countdownTimer');
if (countdownTimer) {
countdownTimer.textContent = timeString;
countdownTimer.className = 'countdown-timer';
countdownTimer.style.display = 'block';
// Set next match start time
nextMatchStartTime = new Date(Date.now() + (timerData.remaining_seconds * 1000));
// Add warning/urgent classes based on time remaining
if (timerData.remaining_seconds <= 60) { // 1 minute
countdownTimer.className = 'countdown-timer urgent';
} else if (timerData.remaining_seconds <= 300) { // 5 minutes
countdownTimer.className = 'countdown-timer warning';
} else {
countdownTimer.className = 'countdown-timer';
// Show next match info
const nextMatchInfo = document.getElementById('nextMatchInfo');
if (nextMatchInfo) {
nextMatchInfo.textContent = `Next match starting in:`;
nextMatchInfo.style.display = 'block';
}
// Start countdown
updateCountdown();
countdownInterval = setInterval(updateCountdown, 1000);
console.log('🔍 DEBUG: Countdown started from timer update');
} else {
// No active timer, hide countdown
const nextMatchInfo = document.getElementById('nextMatchInfo');
const countdownTimer = document.getElementById('countdownTimer');
if (nextMatchInfo) nextMatchInfo.style.display = 'none';
if (countdownTimer) countdownTimer.style.display = 'none';
// Clear countdown interval
if (countdownInterval) {
clearInterval(countdownInterval);
countdownInterval = null;
}
}
}
......@@ -661,25 +673,37 @@
// Handle timer updates from match_timer
const timerData = data.timer_update;
if (timerData.running && timerData.remaining_seconds !== undefined) {
// Format remaining time
const minutes = Math.floor(timerData.remaining_seconds / 60);
const seconds = timerData.remaining_seconds % 60;
const timeString = `${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;
// Clear any existing countdown
if (countdownInterval) {
clearInterval(countdownInterval);
countdownInterval = null;
}
const countdownTimer = document.getElementById('countdownTimer');
if (countdownTimer) {
countdownTimer.textContent = timeString;
countdownTimer.className = 'countdown-timer';
countdownTimer.style.display = 'block';
// Set next match start time
nextMatchStartTime = new Date(Date.now() + (timerData.remaining_seconds * 1000));
// Add warning/urgent classes based on time remaining
if (timerData.remaining_seconds <= 60) { // 1 minute
countdownTimer.className = 'countdown-timer urgent';
} else if (timerData.remaining_seconds <= 300) { // 5 minutes
countdownTimer.className = 'countdown-timer warning';
} else {
countdownTimer.className = 'countdown-timer';
// Show next match info
const nextMatchInfo = document.getElementById('nextMatchInfo');
if (nextMatchInfo) {
nextMatchInfo.textContent = `Next match starting in:`;
nextMatchInfo.style.display = 'block';
}
// Start countdown
updateCountdown();
countdownInterval = setInterval(updateCountdown, 1000);
console.log('🔍 DEBUG: Countdown started from timer update');
} else {
// No active timer, hide countdown
const nextMatchInfo = document.getElementById('nextMatchInfo');
const countdownTimer = document.getElementById('countdownTimer');
if (nextMatchInfo) nextMatchInfo.style.display = 'none';
if (countdownTimer) countdownTimer.style.display = 'none';
// Clear countdown interval
if (countdownInterval) {
clearInterval(countdownInterval);
countdownInterval = null;
}
}
}
......@@ -1138,6 +1162,10 @@
console.log('🔍 DEBUG: WebServerBaseUrl not received via WebChannel, proceeding with WebChannel data fetch');
}
// Check for timer state immediately when page loads
debugTime('Checking timer state on page load');
getTimerStateAndStartCountdown();
// Fetch fixture data directly from WebChannel
debugTime('Fetching fixture data from WebChannel');
fetchFixtureData();
......
......@@ -4,6 +4,7 @@
<meta charset="utf-8">
<title>Results Overlay</title>
<script src="qrc:///qtwebchannel/qwebchannel.js"></script>
<script src="overlay://overlay.js"></script>
<style>
* {
margin: 0;
......@@ -772,6 +773,8 @@
let videoStartTime = null;
let contentDelayTimer = null;
let resultsTimer = null;
let lastPositionLogTime = 0;
const POSITION_LOG_THROTTLE_MS = 500; // Throttle position logs to max 1 per 500ms
// Define showLoadingState for compatibility (results template doesn't use loading state)
function showLoadingState() {
......@@ -797,13 +800,21 @@
// Function to update overlay data (called by Qt WebChannel)
function updateOverlayData(data) {
console.log('DEBUG: updateOverlayData called with data:', data);
console.log('RESULTS TEMPLATE: updateOverlayData called with data:', data);
overlayData = data || {};
// Only update if we have valid data
if (data && (data.outcome || data.result)) {
let result = data.outcome || data.result;
console.log('DEBUG: Processing valid result:', result);
console.log('RESULTS TEMPLATE: Processing valid result:', result);
// Check if this is the same data we already processed (prevent duplicate processing)
const dataHash = JSON.stringify(data);
if (window.lastProcessedDataHash === dataHash) {
console.log('RESULTS TEMPLATE: Duplicate data received, ignoring');
return;
}
window.lastProcessedDataHash = dataHash;
// Always treat the main result as the primary outcome
currentMainResult = result;
......@@ -811,7 +822,7 @@
// Check if under/over result is provided separately
if (data.under_over_result) {
currentUnderOverResult = data.under_over_result;
console.log('DEBUG: Under/over result provided separately:', currentUnderOverResult);
console.log('RESULTS TEMPLATE: Under/over result provided separately:', currentUnderOverResult);
} else {
// Fallback: determine if main result is under/over
if (result === 'UNDER' || result === 'OVER') {
......@@ -824,20 +835,20 @@
if (data.match) {
currentMatch = data.match;
console.log('DEBUG: Match data received:', data.match);
console.log('RESULTS TEMPLATE: Match data received:', data.match);
}
if (data.match_id) {
console.log('DEBUG: Match ID received:', data.match_id);
console.log('RESULTS TEMPLATE: Match ID received:', data.match_id);
// Fetch winning outcomes for this match
fetchWinningOutcomes(data.match_id);
// Check if results have already been shown for this match (handles overlay reloads)
const resultsShownKey = 'results_shown_' + data.match_id;
const alreadyShown = sessionStorage.getItem(resultsShownKey) === 'true';
console.log('DEBUG: Results already shown for match?', alreadyShown);
console.log('RESULTS TEMPLATE: Results already shown for match?', alreadyShown);
if (alreadyShown) {
console.log('DEBUG: Results already shown for this match, displaying immediately');
console.log('RESULTS TEMPLATE: Results already shown for this match, displaying immediately');
contentVisible = true;
showResultsPanel();
showResultsContent();
......@@ -846,11 +857,11 @@
}
// Prepare data and start 5-second timer to show results
console.log('DEBUG: Results data received, preparing animation data');
console.log('RESULTS TEMPLATE: Results data received, preparing animation data');
prepareResultsAnimation();
} else {
console.log('DEBUG: No valid data received, showing loading state');
console.log('RESULTS TEMPLATE: No valid data received, showing loading state');
// No valid data, show loading state
showLoadingState();
}
......@@ -870,38 +881,43 @@
// Update winning bets display
updateWinningBetsDisplay();
// Show results after 5 seconds from data receipt
// Show blue background after 5 seconds from data receipt
setTimeout(() => {
if (!contentVisible) {
contentVisible = true;
console.log('Showing results after 5 seconds from data received');
console.log('RESULTS TEMPLATE: Showing blue background after 5 seconds from data received');
// Mark results as shown in sessionStorage
if (overlayData && overlayData.match_id) {
sessionStorage.setItem('results_shown_' + overlayData.match_id, 'true');
}
showResultsPanel();
showResultsPanel(); // Show blue background
// Show data immediately after background appears
setTimeout(() => {
contentVisible = true;
console.log('RESULTS TEMPLATE: Showing data immediately after background');
showResultsContent();
}, 100); // Small delay to ensure background is visible first
}
}, 5000);
}
// Fetch winning outcomes for the match
function fetchWinningOutcomes(matchId) {
console.log('DEBUG: fetchWinningOutcomes called for match:', matchId);
console.log('RESULTS TEMPLATE: fetchWinningOutcomes called for match:', matchId);
// Use Qt WebChannel to request winning outcomes data
if (window.overlay && window.overlay.getWinningOutcomes) {
console.log('DEBUG: Qt WebChannel available, requesting winning outcomes');
console.log('RESULTS TEMPLATE: Qt WebChannel available, requesting winning outcomes');
try {
const outcomesJson = window.overlay.getWinningOutcomes(matchId);
const outcomesData = JSON.parse(outcomesJson);
console.log('DEBUG: Received winning outcomes:', outcomesData);
console.log('RESULTS TEMPLATE: Received winning outcomes:', outcomesData);
winningOutcomes = outcomesData || [];
updateWinningBetsDisplay();
} catch (error) {
console.error('DEBUG: Failed to get winning outcomes:', error);
console.error('RESULTS TEMPLATE: Failed to get winning outcomes:', error);
// Fallback: show sample data for testing
winningOutcomes = [
{ outcome: 'WIN1', amount: 125.00 },
......@@ -911,7 +927,7 @@
updateWinningBetsDisplay();
}
} else {
console.warn('DEBUG: Qt WebChannel not available for fetching winning outcomes');
console.warn('RESULTS TEMPLATE: Qt WebChannel not available for fetching winning outcomes');
// Fallback: show sample data for testing
winningOutcomes = [
{ outcome: 'WIN1', amount: 125.00 },
......@@ -924,38 +940,51 @@
// Show results panel with fade-in animation
function showResultsPanel() {
console.log('DEBUG: showResultsPanel called');
console.log('RESULTS TEMPLATE: showResultsPanel called');
const resultsPanel = document.getElementById('resultsPanel');
if (resultsPanel) {
console.log('DEBUG: Adding visible class to results panel');
console.log('RESULTS TEMPLATE: Adding visible class to results panel');
resultsPanel.classList.add('visible');
} else {
console.log('DEBUG: ERROR - resultsPanel element not found');
console.log('RESULTS TEMPLATE: ERROR - resultsPanel element not found');
}
}
// Show results content with animation after delay
function showResultsContent() {
console.log('DEBUG: showResultsContent called');
console.log('RESULTS TEMPLATE: showResultsContent called');
const resultsContent = document.getElementById('resultsContent');
if (resultsContent) {
console.log('DEBUG: Adding visible class to results content');
console.log('RESULTS TEMPLATE: Adding visible class to results content');
resultsContent.classList.add('visible');
} else {
console.log('DEBUG: ERROR - resultsContent element not found');
console.log('RESULTS TEMPLATE: ERROR - resultsContent element not found');
}
}
// Handle video position changes (for logging/debugging purposes)
function handlePositionChange(position, duration) {
const currentTime = Date.now();
// Check if video has started playing (position > 0)
if (position > 0 && !videoStarted) {
videoStarted = true;
console.log('Video started playing at position:', position);
console.log('RESULTS TEMPLATE: Video started playing at position:', position);
}
// Log position for debugging
console.log('Video position:', position, 'duration:', duration);
// Check if we've reached 5 seconds and should show results
if (position >= 5 && !contentVisible && overlayData && (overlayData.outcome || overlayData.result)) {
console.log('RESULTS TEMPLATE: Video reached 5 seconds, showing results');
contentVisible = true;
showResultsPanel();
showResultsContent();
}
// Throttle position logging to reduce message bus traffic
if (currentTime - lastPositionLogTime >= POSITION_LOG_THROTTLE_MS) {
console.log('RESULTS TEMPLATE: Video position:', position, 'duration:', duration);
lastPositionLogTime = currentTime;
}
}
// Update fighters display
......@@ -1074,21 +1103,27 @@
}
}
// Request current data from backend (now handled by WebChannel signals)
function requestCurrentData() {
console.log('RESULTS TEMPLATE: requestCurrentData called - data is received via WebChannel signals');
// Data is handled by dataUpdated signal connection, no need to manually request
}
// Initialize when DOM is loaded
document.addEventListener('DOMContentLoaded', function() {
console.log('DEBUG: Results overlay DOM loaded and initialized');
console.log('DEBUG: sessionStorage available:', typeof sessionStorage !== 'undefined');
console.log('RESULTS TEMPLATE: DOM loaded and initialized');
console.log('RESULTS TEMPLATE: sessionStorage available:', typeof sessionStorage !== 'undefined');
// Setup WebChannel communication
// Setup WebChannel communication (includes data polling)
setupWebChannel();
// Panel and content will be shown after 5 seconds when video starts playing
console.log('DEBUG: Waiting for results data to be received');
console.log('RESULTS TEMPLATE: Waiting for results data to be received via WebChannel signals');
// Fallback: show test results after 5 seconds if no data received
// Fallback: show test results after 10 seconds if no data received via signals
setTimeout(() => {
if (!contentVisible) {
console.log('DEBUG: Fallback - No data received after 5 seconds, showing test results');
console.log('RESULTS TEMPLATE: Fallback - No data received after 10 seconds, showing test results');
// Set test data
currentMainResult = 'WIN1';
currentUnderOverResult = 'OVER';
......@@ -1104,94 +1139,87 @@
updateCombinedResultDisplay();
updateWinningBetsDisplay();
}
}, 5000);
}, 10000);
});
// Setup WebChannel communication (similar to fixtures.html)
// Setup WebChannel communication (wait for overlay.js to set up WebChannel)
function setupWebChannel() {
// Check if WebChannel is already set up by overlay.js
if (window.overlay) {
console.log('DEBUG: WebChannel already set up by overlay.js');
console.log('RESULTS TEMPLATE: Waiting for overlay.js WebChannel to be ready...');
// Test WebChannel
if (window.overlay && window.overlay.log) {
window.overlay.log('TEST: WebChannel connection successful');
}
// Listen for data updates from Python
if (window.overlay.dataUpdated) {
window.overlay.dataUpdated.connect(function(data) {
console.log('DEBUG: Received data update from Python:', data);
// Set up global callback for dataUpdated signal (called by overlay.js)
window.onDataUpdated = function(data) {
console.log('RESULTS TEMPLATE: onDataUpdated callback called with:', data);
if (data !== null && data !== undefined) {
updateOverlayData(data);
});
} else {
console.warn('RESULTS TEMPLATE: onDataUpdated callback received null/undefined data');
}
};
// Connect positionChanged signal
// Wait for overlay.js to set up the WebChannel and overlay object
const checkOverlayReady = () => {
if (window.overlay && window.overlayManager && window.overlayManager.webChannelReady) {
console.log('RESULTS TEMPLATE: overlay.js WebChannel ready');
// Connect positionChanged signal if available
if (window.overlay.positionChanged) {
console.log('DEBUG: Connecting positionChanged signal');
console.log('RESULTS TEMPLATE: Connecting positionChanged signal');
window.overlay.positionChanged.connect(function(position, duration) {
if (position !== null && duration !== null) {
handlePositionChange(position, duration);
} else {
console.warn('DEBUG: positionChanged signal received null/undefined parameters');
console.warn('RESULTS TEMPLATE: positionChanged signal received null/undefined parameters');
}
});
}
return;
}
// Fallback: setup WebChannel if overlay.js didn't do it
if (typeof qt !== 'undefined' && qt.webChannelTransport) {
// Try to get current data immediately when WebChannel is ready
console.log('RESULTS TEMPLATE: Attempting to get current data from WebChannel');
try {
new QWebChannel(qt.webChannelTransport, function(channel) {
console.log('DEBUG: WebChannel connected successfully (fallback)');
// Connect to overlay object
window.overlay = channel.objects.overlay;
// Listen for data updates from Python
if (window.overlay && window.overlay.dataUpdated) {
window.overlay.dataUpdated.connect(function(data) {
console.log('DEBUG: Received data update from Python:', data);
updateOverlayData(data);
});
}
// Connect positionChanged signal
if (window.overlay.positionChanged) {
console.log('DEBUG: Connecting positionChanged signal');
window.overlay.positionChanged.connect(function(position, duration) {
if (position !== null && duration !== null) {
handlePositionChange(position, duration);
if (window.overlay && window.overlay.getCurrentData) {
const currentDataJson = window.overlay.getCurrentData();
console.log('RESULTS TEMPLATE: Got current data JSON:', currentDataJson);
if (currentDataJson) {
const currentData = JSON.parse(currentDataJson);
console.log('RESULTS TEMPLATE: Parsed current data:', currentData);
if (currentData && (currentData.outcome || currentData.result)) {
console.log('RESULTS TEMPLATE: Found valid data in current data, processing');
updateOverlayData(currentData);
} else {
console.warn('DEBUG: positionChanged signal received null/undefined parameters');
console.log('RESULTS TEMPLATE: No valid result data in current data');
}
});
}
});
} catch (e) {
console.log('DEBUG: Failed to setup WebChannel:', e);
}
} catch (error) {
console.error('RESULTS TEMPLATE: Failed to get current data:', error);
}
console.log('RESULTS TEMPLATE: WebChannel setup completed, signals connected');
} else {
console.log('DEBUG: WebChannel not available');
// Keep checking until overlay.js has set up the WebChannel
setTimeout(checkOverlayReady, 50);
}
};
checkOverlayReady();
}
// Export functions for external use
window.setOutcome = setOutcome;
window.updateOverlayData = updateOverlayData;
</script>
<!--
IMPORTANT: When creating or editing custom templates, always maintain this script tag:
qrc:///qtwebchannel/qwebchannel.js - Required for Qt WebChannel communication
IMPORTANT: When creating or editing custom templates, always maintain these script tags:
1. qrc:///qtwebchannel/qwebchannel.js - Required for Qt WebChannel communication
2. overlay://overlay.js - Required for overlay functionality and data updates
This script enables communication between the Qt application and the overlay template.
The results.html template handles its own WebChannel setup and does not use overlay.js
to avoid conflicts with the custom overlay elements.
These scripts enable communication between the Qt application and the overlay template.
The results.html template uses overlay.js for WebChannel setup and adds custom dataUpdated signal handling.
NOTE: When editing this template, never remove the qwebchannel.js script source!
NOTE: When editing this template, never remove these script sources!
The overlay:// custom scheme ensures JavaScript files work for both built-in and uploaded templates.
-->
<script src="qrc:///qtwebchannel/qwebchannel.js"></script>
</body>
</html>
\ No newline at end of file
......@@ -47,6 +47,24 @@ class OverlayManager {
});
}
// Connect dataUpdated signal for templates that need it (like results.html)
if (window.overlay.dataUpdated) {
window.overlay.dataUpdated.connect((data) => {
if (data !== null && data !== undefined) {
// Call a global callback if it exists (for results.html and other templates)
if (window.onDataUpdated) {
window.onDataUpdated(data);
}
console.log('dataUpdated signal received:', data);
} else {
console.warn('dataUpdated signal received null/undefined data');
}
});
}
// Mark WebChannel as ready
this.webChannelReady = true;
// Process pending updates after full initialization
setTimeout(() => this.processPendingUpdates(), 100);
console.log('WebChannel connected and ready');
......@@ -80,6 +98,24 @@ class OverlayManager {
}
});
// Connect dataUpdated signal for templates that need it (like results.html)
if (overlay.dataUpdated) {
overlay.dataUpdated.connect((data) => {
if (data !== null && data !== undefined) {
// Call a global callback if it exists (for results.html and other templates)
if (window.onDataUpdated) {
window.onDataUpdated(data);
}
console.log('dataUpdated signal received:', data);
} else {
console.warn('dataUpdated signal received null/undefined data');
}
});
}
// Mark WebChannel as ready
this.webChannelReady = true;
// Process pending updates after full initialization
setTimeout(() => this.processPendingUpdates(), 100);
console.log('WebChannel connected via fallback method');
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment