Fix game freeze with no images loaded
Critical fix for desktop startup:
- Fixed startGame() function to properly handle new customImages object format
- Previously trying to call .length on object instead of array
- Added proper backward compatibility checking for both old array and new object formats
- Added comprehensive logging to debug image management screen freeze
- Now correctly counts custom images from both task and consequence categories
Fixes error where:
- User clicks Start Game with no images
- Game redirects to image management screen but freezes
- TypeError: customImages.length when customImages is {task: [], consequence: []}
Error resolved with proper object structure handling and logging.
This commit is contained in:
parent
85ea7f8938
commit
aa3b7d8a1c
65
game.js
65
game.js
|
|
@ -312,6 +312,9 @@ class TaskChallengeGame {
|
|||
// Theme selector
|
||||
document.getElementById('theme-dropdown').addEventListener('change', (e) => this.changeTheme(e.target.value));
|
||||
|
||||
// Options menu toggle
|
||||
document.getElementById('options-menu-btn').addEventListener('click', () => this.toggleOptionsMenu());
|
||||
|
||||
// Music controls
|
||||
document.getElementById('music-toggle').addEventListener('click', () => this.toggleMusic());
|
||||
document.getElementById('loop-btn').addEventListener('click', () => this.toggleLoop());
|
||||
|
|
@ -711,29 +714,23 @@ class TaskChallengeGame {
|
|||
}
|
||||
|
||||
updateStartScreenStatus() {
|
||||
// Status message removed for cleaner home screen interface
|
||||
const statusDiv = document.getElementById('start-screen-status');
|
||||
if (!statusDiv) return;
|
||||
if (statusDiv) {
|
||||
statusDiv.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
toggleOptionsMenu() {
|
||||
const optionsMenu = document.getElementById('options-menu');
|
||||
const button = document.getElementById('options-menu-btn');
|
||||
|
||||
const totalImages = gameData.discoveredTaskImages.length + gameData.discoveredConsequenceImages.length;
|
||||
const customImages = this.dataManager.get('customImages') || [];
|
||||
const totalAvailable = totalImages + customImages.length;
|
||||
|
||||
if (totalAvailable === 0) {
|
||||
statusDiv.innerHTML = `
|
||||
<div class="status-warning">
|
||||
⚠️ No images found!
|
||||
<br>Go to "Manage Images" to upload images or scan directories.
|
||||
</div>
|
||||
`;
|
||||
statusDiv.style.display = 'block';
|
||||
if (optionsMenu.style.display === 'none' || optionsMenu.style.display === '') {
|
||||
optionsMenu.style.display = 'block';
|
||||
button.textContent = '⚙️ Close Options';
|
||||
} else {
|
||||
statusDiv.innerHTML = `
|
||||
<div class="status-success">
|
||||
✅ Ready to play! Found ${totalAvailable} images
|
||||
(${totalImages} from directories, ${customImages.length} uploaded)
|
||||
</div>
|
||||
`;
|
||||
statusDiv.style.display = 'block';
|
||||
optionsMenu.style.display = 'none';
|
||||
button.textContent = '⚙️ Options';
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -852,26 +849,35 @@ class TaskChallengeGame {
|
|||
|
||||
// Image Management Methods
|
||||
showImageManagement() {
|
||||
console.log('showImageManagement() called');
|
||||
this.showScreen('image-management-screen');
|
||||
console.log('Screen switched to image-management-screen');
|
||||
this.setupImageManagementEventListeners();
|
||||
console.log('Event listeners set up');
|
||||
|
||||
// Wait for image discovery to complete before loading gallery
|
||||
if (!this.imageDiscoveryComplete) {
|
||||
console.log('Image discovery not complete, waiting...');
|
||||
const gallery = document.getElementById('image-gallery');
|
||||
gallery.innerHTML = '<div class="loading">Discovering images...</div>';
|
||||
|
||||
// Wait and try again
|
||||
setTimeout(() => {
|
||||
console.log('Timeout reached, checking discovery status...');
|
||||
if (this.imageDiscoveryComplete) {
|
||||
console.log('Discovery complete, loading gallery...');
|
||||
this.loadImageGallery();
|
||||
} else {
|
||||
console.log('Discovery still not complete, waiting longer...');
|
||||
gallery.innerHTML = '<div class="loading">Still discovering images... Please wait</div>';
|
||||
setTimeout(() => this.loadImageGallery(), 1000);
|
||||
}
|
||||
}, 500);
|
||||
} else {
|
||||
console.log('Image discovery already complete, loading gallery...');
|
||||
this.loadImageGallery();
|
||||
}
|
||||
console.log('showImageManagement() completed');
|
||||
}
|
||||
|
||||
switchImageTab(tabType) {
|
||||
|
|
@ -1024,14 +1030,21 @@ class TaskChallengeGame {
|
|||
}
|
||||
|
||||
loadImageGallery() {
|
||||
console.log('loadImageGallery() called');
|
||||
// Load both task and consequence image galleries
|
||||
console.log('Cleaning up invalid images...');
|
||||
this.cleanupInvalidImages(); // Clean up invalid images first
|
||||
console.log('Loading task images...');
|
||||
this.loadTaskImages();
|
||||
console.log('Loading consequence images...');
|
||||
this.loadConsequenceImages();
|
||||
console.log('Updating image counts...');
|
||||
this.updateImageCounts();
|
||||
|
||||
// Initialize with task tab active and update controls
|
||||
console.log('Updating gallery controls for task tab...');
|
||||
this.updateImageGalleryControls('task');
|
||||
console.log('loadImageGallery() completed');
|
||||
}
|
||||
|
||||
loadTaskImages() {
|
||||
|
|
@ -1831,9 +1844,17 @@ ${usagePercent > 85 ? '⚠️ Storage getting full - consider deleting some imag
|
|||
|
||||
// Check if we have any images available
|
||||
const totalImages = gameData.discoveredTaskImages.length + gameData.discoveredConsequenceImages.length;
|
||||
const customImages = this.dataManager.get('customImages') || [];
|
||||
const customImages = this.dataManager.get('customImages') || { task: [], consequence: [] };
|
||||
|
||||
if (totalImages === 0 && customImages.length === 0) {
|
||||
// Handle both old array format and new object format for backward compatibility
|
||||
let customImageCount = 0;
|
||||
if (Array.isArray(customImages)) {
|
||||
customImageCount = customImages.length;
|
||||
} else {
|
||||
customImageCount = (customImages.task || []).length + (customImages.consequence || []).length;
|
||||
}
|
||||
|
||||
if (totalImages === 0 && customImageCount === 0) {
|
||||
// No images available - guide user to add images
|
||||
this.showNotification('No images found! Please upload images or scan directories first.', 'error', 5000);
|
||||
this.showScreen('image-management-screen');
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 1020 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 MiB |
74
index.html
74
index.html
|
|
@ -43,42 +43,52 @@
|
|||
<h2>Ready to Start?</h2>
|
||||
<p>Complete tasks, but beware of skipping - there are consequences!</p>
|
||||
|
||||
<!-- Status Message -->
|
||||
<div id="start-screen-status" class="status-message" style="display: none;"></div>
|
||||
|
||||
<!-- Theme Selector -->
|
||||
<div class="theme-selector">
|
||||
<label for="theme-dropdown" class="theme-label">Choose Your Vibe:</label>
|
||||
<select id="theme-dropdown" class="theme-dropdown">
|
||||
<option value="ocean">🌊 Ocean Blue</option>
|
||||
<option value="sunset">🌅 Warm Sunset</option>
|
||||
<option value="forest">🌲 Nature Green</option>
|
||||
<option value="midnight">🌙 Midnight Dark</option>
|
||||
<option value="pastel">🌸 Soft Pastel</option>
|
||||
<option value="neon">⚡ Neon Cyber</option>
|
||||
<option value="autumn">🍂 Autumn Vibes</option>
|
||||
<option value="monochrome">⚫ Monochrome</option>
|
||||
</select>
|
||||
<!-- Main Action Buttons -->
|
||||
<div class="main-actions">
|
||||
<button id="start-btn" class="btn btn-primary">Start Game</button>
|
||||
<button id="manage-tasks-btn" class="btn btn-secondary">Manage Tasks</button>
|
||||
<button id="manage-images-btn" class="btn btn-secondary">Manage Images</button>
|
||||
</div>
|
||||
|
||||
<!-- Data Management -->
|
||||
<div class="data-controls">
|
||||
<button id="export-btn" class="btn btn-secondary" title="Export Save File">
|
||||
<span class="btn-text">💾 Export</span>
|
||||
<span class="btn-loading" style="display: none;">⏳ Exporting...</span>
|
||||
</button>
|
||||
<button id="import-btn" class="btn btn-secondary" title="Import Save File">
|
||||
<span class="btn-text">📁 Import</span>
|
||||
<span class="btn-loading" style="display: none;">⏳ Importing...</span>
|
||||
</button>
|
||||
<!-- Options Menu -->
|
||||
<div class="options-section">
|
||||
<button id="options-menu-btn" class="btn btn-tertiary">⚙️ Options</button>
|
||||
<div id="options-menu" class="options-menu" style="display: none;">
|
||||
<!-- Theme Selector -->
|
||||
<div class="option-item theme-selector">
|
||||
<label for="theme-dropdown" class="option-label">Choose Your Vibe:</label>
|
||||
<select id="theme-dropdown" class="theme-dropdown">
|
||||
<option value="ocean">🌊 Ocean Blue</option>
|
||||
<option value="sunset">🌅 Warm Sunset</option>
|
||||
<option value="forest">🌲 Nature Green</option>
|
||||
<option value="midnight">🌙 Midnight Dark</option>
|
||||
<option value="pastel">🌸 Soft Pastel</option>
|
||||
<option value="neon">⚡ Neon Cyber</option>
|
||||
<option value="autumn">🍂 Autumn Vibes</option>
|
||||
<option value="monochrome">⚫ Monochrome</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Data Management -->
|
||||
<div class="option-item data-controls">
|
||||
<button id="import-btn" class="btn btn-option" title="Import Save File">
|
||||
<span class="btn-text"><EFBFBD> Import</span>
|
||||
<span class="btn-loading" style="display: none;">⏳ Importing...</span>
|
||||
</button>
|
||||
<button id="export-btn" class="btn btn-option" title="Export Save File">
|
||||
<span class="btn-text"><EFBFBD> Export</span>
|
||||
<span class="btn-loading" style="display: none;">⏳ Exporting...</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Other Options -->
|
||||
<div class="option-item other-controls">
|
||||
<button id="stats-btn" class="btn btn-option" title="View Statistics">📊 Stats</button>
|
||||
<button id="help-btn" class="btn btn-option" title="Keyboard Shortcuts & Help">❓ Help</button>
|
||||
</div>
|
||||
</div>
|
||||
<input type="file" id="import-file" accept=".json" style="display: none;">
|
||||
<button id="stats-btn" class="btn btn-secondary" title="View Statistics">📊 Stats</button>
|
||||
<button id="help-btn" class="btn btn-secondary" title="Keyboard Shortcuts & Help">❓ Help</button>
|
||||
</div>
|
||||
|
||||
<button id="start-btn" class="btn btn-primary">Start Game</button>
|
||||
<button id="manage-tasks-btn" class="btn btn-secondary">Manage Tasks</button>
|
||||
<button id="manage-images-btn" class="btn btn-secondary">Manage Images</button>
|
||||
</div>
|
||||
|
||||
<!-- Task Management Screen -->
|
||||
|
|
|
|||
84
styles.css
84
styles.css
|
|
@ -865,6 +865,90 @@ body {
|
|||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* Options Menu Styles */
|
||||
.options-section {
|
||||
margin-top: 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.btn-tertiary {
|
||||
background: #6c757d;
|
||||
color: white;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.btn-tertiary:hover {
|
||||
background: #545b62;
|
||||
}
|
||||
|
||||
.options-menu {
|
||||
background: #f8f9fa;
|
||||
border: 1px solid #dee2e6;
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin-top: 10px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.option-item {
|
||||
margin-bottom: 15px;
|
||||
padding-bottom: 15px;
|
||||
border-bottom: 1px solid #e9ecef;
|
||||
}
|
||||
|
||||
.option-item:last-child {
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.option-label {
|
||||
display: block;
|
||||
font-weight: 600;
|
||||
margin-bottom: 8px;
|
||||
color: #495057;
|
||||
}
|
||||
|
||||
.theme-dropdown {
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
border: 1px solid #ced4da;
|
||||
border-radius: 4px;
|
||||
font-size: 0.95em;
|
||||
}
|
||||
|
||||
.data-controls, .other-controls {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.btn-option {
|
||||
background: #e9ecef;
|
||||
color: #495057;
|
||||
padding: 8px 16px;
|
||||
font-size: 0.9em;
|
||||
min-width: auto;
|
||||
}
|
||||
|
||||
.btn-option:hover {
|
||||
background: #dee2e6;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.main-actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.main-actions .btn {
|
||||
width: 100%;
|
||||
max-width: 300px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.mercy-cost {
|
||||
display: block;
|
||||
font-size: 0.8em;
|
||||
|
|
|
|||
Loading…
Reference in New Issue