@@ -844,10 +1358,7 @@
document.getElementById('include-standard-tasks').checked = quickPlaySettings.includeStandardTasks;
document.getElementById('include-scenario-tasks').checked = quickPlaySettings.includeScenarioTasks;
- // Apply visual settings
- document.getElementById('popup-frequency').value = quickPlaySettings.popupFrequency;
- document.getElementById('popup-duration').value = quickPlaySettings.popupDuration;
- document.getElementById('enable-flash-messages').checked = quickPlaySettings.enableFlashMessages;
+ // Visual settings now managed by popup image management screen
// Apply consequence settings
document.getElementById('consequence-chance').value = quickPlaySettings.consequenceChance;
@@ -1579,15 +2090,7 @@
});
// Visual settings
- document.getElementById('popup-frequency').addEventListener('change', (e) => {
- quickPlaySettings.popupFrequency = e.target.value;
- });
- document.getElementById('popup-duration').addEventListener('change', (e) => {
- quickPlaySettings.popupDuration = e.target.value;
- });
- document.getElementById('enable-flash-messages').addEventListener('change', (e) => {
- quickPlaySettings.enableFlashMessages = e.target.checked;
- });
+ // Visual settings now managed by popup image management screen
// Consequence settings
document.getElementById('consequence-chance').addEventListener('input', (e) => {
@@ -1604,6 +2107,14 @@
document.getElementById('manage-tasks-btn').addEventListener('click', showTaskManagement);
document.getElementById('back-to-setup-btn').addEventListener('click', backToSetup);
+ // Message management buttons
+ document.getElementById('manage-messages-btn').addEventListener('click', showMessageManagement);
+ document.getElementById('back-to-setup-from-messages-btn').addEventListener('click', backToSetup);
+
+ // Popup image management buttons
+ document.getElementById('manage-popup-images-btn').addEventListener('click', showPopupImageManagement);
+ document.getElementById('back-to-setup-from-popup-images-btn').addEventListener('click', backToSetup);
+
// Task management functionality
document.getElementById('main-tasks-tab').addEventListener('click', () => showTaskTab('main'));
document.getElementById('consequence-tasks-tab').addEventListener('click', () => showTaskTab('consequence'));
@@ -2282,6 +2793,14 @@
}
}
+ // Initialize flash message system
+ initializeFlashMessages();
+
+ // Trigger welcome message
+ setTimeout(() => {
+ triggerEventFlashMessage('gameStart');
+ }, 3000); // Show after 3 seconds
+
// Start timer
startGameTimer(config.timeLimit);
@@ -2458,6 +2977,9 @@
// Stop the timer
stopTaskTimer();
+ // Trigger achievement flash message
+ triggerEventFlashMessage('taskComplete');
+
// Check if this was a consequence task
if (isConsequenceTask || task.isConsequence) {
console.log('✅ Consequence task completed - returning to normal tasks');
@@ -2539,6 +3061,9 @@
function quickPlaySkipTask(task) {
console.log('⏭️ Quick Play task skipped:', task.text);
+ // Trigger persistence flash message
+ triggerEventFlashMessage('taskSkip');
+
// Check if this is already a consequence task
if (isConsequenceTask) {
console.log('❌ Cannot skip consequence task - must be completed');
@@ -3001,6 +3526,9 @@
console.log('Setting isGameRunning to false');
isGameRunning = false;
+ // Stop flash message system
+ stopFlashMessageSystem();
+
// Clean up game instance
if (gameInstance) {
console.log('Cleaning up game instance');
@@ -3207,34 +3735,33 @@
function configureGameSystems(config) {
if (!gameInstance) return;
- // Configure popup manager
+ // Configure popup manager with new comprehensive settings
if (gameInstance.popupImageManager) {
- const frequencyMap = {
- 'low': { min: 180000, max: 300000 }, // 3-5 min
- 'medium': { min: 120000, max: 180000 }, // 2-3 min
- 'high': { min: 60000, max: 120000 }, // 1-2 min
- 'constant': { min: 30000, max: 60000 } // 30-60s
- };
+ const popupSettings = JSON.parse(localStorage.getItem('popupImageConfig') || '{}');
- const durationMap = {
- 'short': { min: 3000, max: 5000 },
- 'medium': { min: 5000, max: 8000 },
- 'long': { min: 8000, max: 12000 }
- };
-
- gameInstance.popupImageManager.updateConfig({
- frequency: frequencyMap[config.popupFrequency],
- duration: durationMap[config.popupDuration]
- });
-
- // Start the periodic popup system
- gameInstance.popupImageManager.startPeriodicPopups();
- console.log('🚀 Started periodic popup system with frequency:', config.popupFrequency, 'duration:', config.popupDuration);
+ if (popupSettings.enabled !== false) {
+ // Configure with comprehensive settings
+ gameInstance.popupImageManager.updatePeriodicSettings({
+ minInterval: popupSettings.minInterval || 120,
+ maxInterval: popupSettings.maxInterval || 180,
+ displayDuration: popupSettings.displayDuration || 8
+ });
+
+ // Update full configuration
+ gameInstance.popupImageManager.updateConfig(popupSettings);
+
+ // Start the periodic popup system
+ gameInstance.popupImageManager.startPeriodicPopups();
+ console.log('🚀 Started enhanced popup system with settings:', popupSettings);
+ } else {
+ console.log('📷 Popup images disabled');
+ }
}
- // Configure flash messages
+ // Configure flash messages (managed through message management screen)
if (gameInstance.flashMessageManager) {
- gameInstance.flashMessageManager.enabled = config.enableFlashMessages;
+ const flashSettings = JSON.parse(localStorage.getItem('flashMessageConfig') || '{}');
+ gameInstance.flashMessageManager.enabled = flashSettings.enabled !== false;
}
// Configure audio
@@ -3439,9 +3966,11 @@
if (gameInstance && isGameRunning) {
if (gameInstance.gameState.isPaused) {
gameInstance.resumeGame();
+ resumeFlashMessageSystem();
document.getElementById('pause-game-btn').innerHTML = '⏸️ Pause';
} else {
gameInstance.pauseGame();
+ pauseFlashMessageSystem();
document.getElementById('pause-game-btn').innerHTML = '▶️ Resume';
}
}
@@ -4533,6 +5062,1459 @@
// Focus the confirm button
setTimeout(() => confirmBtn.focus(), 100);
}
+
+ // ===== MESSAGE MANAGEMENT FUNCTIONS =====
+
+ function showMessageManagement() {
+ console.log('💬 Opening message management');
+ document.getElementById('quick-play-setup').style.display = 'none';
+ document.getElementById('quick-play-message-management').style.display = 'block';
+ initializeMessageManagement();
+ }
+
+ function backToQuickPlay() {
+ console.log('⬅️ Returning to Quick Play setup');
+ document.getElementById('quick-play-message-management').style.display = 'none';
+ document.getElementById('popup-image-management').style.display = 'none';
+ document.getElementById('quick-play-setup').style.display = 'block';
+ }
+
+ function showPopupImageManagement() {
+ console.log('🖼️ Opening popup image management');
+ document.getElementById('quick-play-setup').style.display = 'none';
+ document.getElementById('popup-image-management').style.display = 'block';
+ initializePopupImageManagement();
+ }
+
+ function initializeMessageManagement() {
+ // Set up tab switching
+ setupMessageTabs();
+
+ // Load flash message settings
+ loadFlashMessageSettings();
+
+ // Load appearance settings
+ loadMessageAppearanceSettings();
+
+ // Set up event listeners
+ setupMessageManagementEventListeners();
+
+ // Load existing messages
+ loadExistingMessages();
+ }
+
+ function initializePopupImageManagement() {
+ // Load popup image settings
+ loadPopupImageSettingsMain();
+
+ // Set up event listeners for popup image management
+ setupPopupImageManagementEventListeners();
+
+ // Update display values
+ updatePopupImageDisplays();
+ }
+
+ function setupMessageTabs() {
+ const tabButtons = document.querySelectorAll('.message-tab-btn');
+ const sections = document.querySelectorAll('.message-section');
+
+ tabButtons.forEach(button => {
+ button.addEventListener('click', () => {
+ // Remove active class from all tabs and sections
+ tabButtons.forEach(btn => btn.classList.remove('active'));
+ sections.forEach(section => section.classList.remove('active'));
+
+ // Add active class to clicked tab and corresponding section
+ button.classList.add('active');
+ let sectionId;
+ if (button.dataset.type === 'flash') {
+ sectionId = 'flash-messages-section';
+ } else if (button.dataset.type === 'appearance') {
+ sectionId = 'message-appearance-section';
+ } else if (button.dataset.type === 'import-export') {
+ sectionId = 'import-export-section';
+ }
+
+ const section = document.getElementById(sectionId);
+ if (section) {
+ section.classList.add('active');
+ }
+ });
+ });
+ }
+
+ function loadFlashMessageSettings() {
+ // Load flash message settings from localStorage or defaults
+ const flashSettings = JSON.parse(localStorage.getItem('flashMessageConfig') || '{}');
+
+ // Apply settings to UI elements
+ document.getElementById('flash-messages-enabled').checked = flashSettings.enabled !== false;
+ document.getElementById('display-duration').value = flashSettings.displayDuration || 3000;
+ document.getElementById('interval-delay').value = flashSettings.intervalDelay || 45000;
+ document.getElementById('time-variation').value = flashSettings.timeVariation || 5000;
+ document.getElementById('event-based-messages').checked = flashSettings.eventBased !== false;
+ document.getElementById('pause-on-hover').checked = flashSettings.pauseOnHover || false;
+
+ // Update display values
+ updateRangeDisplays();
+ }
+
+ function loadPopupImageSettings() {
+ // Load popup image settings from localStorage or defaults
+ const popupSettings = JSON.parse(localStorage.getItem('popupImageConfig') || '{}');
+
+ // Apply settings to UI elements
+ document.getElementById('popup-images-enabled').checked = popupSettings.enabled || false;
+ document.getElementById('popup-count-mode').value = popupSettings.countMode || 'fixed';
+ document.getElementById('popup-image-count').value = popupSettings.imageCount || 3;
+ document.getElementById('popup-duration-mode').value = popupSettings.durationMode || 'fixed';
+ document.getElementById('popup-display-duration').value = popupSettings.displayDuration || 8;
+ document.getElementById('popup-positioning-qp').value = popupSettings.positioning || 'random';
+ document.getElementById('popup-allow-overlap').checked = popupSettings.allowOverlap || false;
+ document.getElementById('popup-viewport-width').value = popupSettings.viewportWidth || 35;
+ document.getElementById('popup-viewport-height').value = popupSettings.viewportHeight || 40;
+ document.getElementById('popup-min-width').value = popupSettings.minWidth || 200;
+ document.getElementById('popup-max-width').value = popupSettings.maxWidth || 500;
+ document.getElementById('popup-min-height').value = popupSettings.minHeight || 150;
+ document.getElementById('popup-max-height').value = popupSettings.maxHeight || 400;
+ document.getElementById('popup-fade-animation').checked = popupSettings.fadeAnimation || false;
+ document.getElementById('popup-blur-background').checked = popupSettings.blurBackground || false;
+ document.getElementById('popup-show-timer').checked = popupSettings.showTimer || false;
+ document.getElementById('popup-prevent-close').checked = popupSettings.preventClose || false;
+
+ // Update display values
+ updatePopupDisplays();
+ }
+
+ function loadMessageAppearanceSettings() {
+ // Load appearance settings from localStorage or defaults
+ const appearanceSettings = JSON.parse(localStorage.getItem('flashMessageAppearance') || '{}');
+ console.log('🔍 Loading appearance settings:', appearanceSettings);
+
+ // Apply settings to UI elements
+ document.getElementById('message-position').value = appearanceSettings.position || 'center';
+ document.getElementById('animation-style').value = appearanceSettings.animation || 'fade';
+ document.getElementById('font-size').value = appearanceSettings.fontSize || 24;
+ document.getElementById('message-opacity').value = appearanceSettings.opacity || 90;
+ document.getElementById('text-color').value = appearanceSettings.textColor || '#ffffff';
+ document.getElementById('background-color').value = appearanceSettings.backgroundColor || '#007bff';
+ document.getElementById('remove-background').checked = appearanceSettings.removeBackground || false;
+ document.getElementById('text-stroke').checked = appearanceSettings.textStroke || false;
+ document.getElementById('stroke-color').value = appearanceSettings.strokeColor || '#000000';
+ document.getElementById('stroke-width').value = appearanceSettings.strokeWidth || 2;
+
+ console.log('✅ Applied appearance settings to UI controls');
+
+ // Update display values
+ updateAppearanceDisplays();
+
+ // Show/hide stroke options
+ toggleStrokeOptions();
+ }
+
+ function setupMessageManagementEventListeners() {
+ // Range slider listeners for real-time updates
+ document.getElementById('display-duration').addEventListener('input', updateRangeDisplays);
+ document.getElementById('interval-delay').addEventListener('input', updateRangeDisplays);
+ document.getElementById('time-variation').addEventListener('input', updateRangeDisplays);
+ document.getElementById('font-size').addEventListener('input', updateAppearanceDisplays);
+ document.getElementById('message-opacity').addEventListener('input', updateAppearanceDisplays);
+ document.getElementById('stroke-width').addEventListener('input', updateAppearanceDisplays);
+
+ // Appearance real-time update listeners
+ document.getElementById('message-position').addEventListener('change', updateFlashMessageAppearanceRealTime);
+ document.getElementById('animation-style').addEventListener('change', updateFlashMessageAppearanceRealTime);
+ document.getElementById('text-color').addEventListener('change', updateFlashMessageAppearanceRealTime);
+ document.getElementById('background-color').addEventListener('change', updateFlashMessageAppearanceRealTime);
+ document.getElementById('remove-background').addEventListener('change', updateFlashMessageAppearanceRealTime);
+ document.getElementById('text-stroke').addEventListener('change', function() {
+ toggleStrokeOptions();
+ updateFlashMessageAppearanceRealTime();
+ });
+ document.getElementById('stroke-color').addEventListener('change', updateFlashMessageAppearanceRealTime);
+ document.getElementById('stroke-width').addEventListener('input', updateFlashMessageAppearanceRealTime);
+
+ // Popup settings are now managed in separate popup image management screen
+
+ // Message text area listener
+ document.getElementById('new-message-text').addEventListener('input', updateCharCount);
+
+ // Button listeners
+ document.getElementById('add-message-btn').addEventListener('click', addNewMessage);
+ document.getElementById('preview-message-btn').addEventListener('click', previewMessage);
+ document.getElementById('test-flash-message').addEventListener('click', testFlashMessage);
+ document.getElementById('test-behavior-settings').addEventListener('click', testBehaviorSettings);
+ document.getElementById('save-message-settings-btn').addEventListener('click', saveAllMessageSettings);
+ document.getElementById('reset-appearance-btn').addEventListener('click', resetAppearanceSettings);
+ document.getElementById('preview-appearance-btn').addEventListener('click', previewAppearanceSettings);
+
+ // Import/Export listeners
+ document.getElementById('export-all-messages-btn').addEventListener('click', () => exportMessages('all'));
+ document.getElementById('export-enabled-messages-btn').addEventListener('click', () => exportMessages('enabled'));
+ document.getElementById('import-messages-btn').addEventListener('click', importMessages);
+ document.getElementById('reset-to-defaults-btn').addEventListener('click', resetToDefaults);
+ }
+
+ function updateRangeDisplays() {
+ document.getElementById('duration-display').textContent = (document.getElementById('display-duration').value / 1000).toFixed(1) + 's';
+ document.getElementById('interval-display').textContent = (document.getElementById('interval-delay').value / 1000).toFixed(0) + 's';
+ document.getElementById('variation-display').textContent = '±' + (document.getElementById('time-variation').value / 1000).toFixed(0) + 's';
+ }
+
+ function updatePopupDisplays() {
+ document.getElementById('popup-image-count-value').textContent = document.getElementById('popup-image-count').value;
+ document.getElementById('popup-display-duration-value').textContent = document.getElementById('popup-display-duration').value + 's';
+ document.getElementById('popup-viewport-width-value').textContent = document.getElementById('popup-viewport-width').value + '%';
+ document.getElementById('popup-viewport-height-value').textContent = document.getElementById('popup-viewport-height').value + '%';
+ }
+
+ function updateAppearanceDisplays() {
+ document.getElementById('font-size-display').textContent = document.getElementById('font-size').value + 'px';
+ document.getElementById('opacity-display').textContent = document.getElementById('message-opacity').value + '%';
+ document.getElementById('stroke-width-display').textContent = document.getElementById('stroke-width').value + 'px';
+ }
+
+ function updateFlashMessageAppearanceRealTime() {
+ // Update flash message system in real-time if it's running
+ if (typeof flashMessageSystem !== 'undefined' && flashMessageSystem) {
+ // Get current appearance settings from the form
+ const appearanceSettings = {
+ position: document.getElementById('message-position').value,
+ animation: document.getElementById('animation-style').value,
+ fontSize: parseInt(document.getElementById('font-size').value),
+ opacity: parseInt(document.getElementById('message-opacity').value),
+ textColor: document.getElementById('text-color').value,
+ backgroundColor: document.getElementById('background-color').value,
+ removeBackground: document.getElementById('remove-background').checked,
+ textStroke: document.getElementById('text-stroke').checked,
+ strokeColor: document.getElementById('stroke-color').value,
+ strokeWidth: parseInt(document.getElementById('stroke-width').value)
+ };
+
+ // Update the flash message system config
+ flashMessageSystem.config = {
+ ...flashMessageSystem.config,
+ ...appearanceSettings
+ };
+
+ // Recreate the message element with new styles
+ createFlashMessageElement();
+
+ console.log('⚡ Flash message appearance updated in real-time');
+ }
+ }
+
+ function toggleStrokeOptions() {
+ const strokeEnabled = document.getElementById('text-stroke').checked;
+ const strokeOptions = document.getElementById('stroke-options');
+ strokeOptions.style.display = strokeEnabled ? 'flex' : 'none';
+ }
+
+ function updatePopupCountMode() {
+ const mode = document.getElementById('popup-count-mode').value;
+ document.getElementById('popup-fixed-count').style.display = mode === 'fixed' ? 'block' : 'none';
+ document.getElementById('popup-range-count').style.display = mode === 'range' ? 'block' : 'none';
+ }
+
+ function updatePopupDurationMode() {
+ const mode = document.getElementById('popup-duration-mode').value;
+ document.getElementById('popup-fixed-duration').style.display = mode === 'fixed' ? 'block' : 'none';
+ document.getElementById('popup-range-duration').style.display = mode === 'range' ? 'block' : 'none';
+ }
+
+ function updateCharCount() {
+ const textarea = document.getElementById('new-message-text');
+ const counter = document.getElementById('message-char-count');
+ counter.textContent = textarea.value.length;
+ }
+
+ function loadExistingMessages() {
+ // Load messages from localStorage or use defaults
+ const messageList = document.getElementById('message-list');
+ const messageStats = document.getElementById('message-stats');
+
+ if (!messageList || !messageStats) return;
+
+ // Get custom messages or use defaults
+ let allMessages = JSON.parse(localStorage.getItem('customFlashMessages') || 'null');
+
+ // If no custom messages, use default messages from gameData
+ if (!allMessages) {
+ allMessages = [
+ // Motivational messages
+ { id: 1, text: "Good goon! Keep stroking and watching!", category: "motivational", enabled: true },
+ { id: 2, text: "Every edge makes you more submissive!", category: "motivational", enabled: true },
+ { id: 3, text: "Porn is your new reality!", category: "motivational", enabled: true },
+ { id: 4, text: "You're becoming such a good little gooner!", category: "motivational", enabled: true },
+ { id: 5, text: "Real men fuck while you watch!", category: "motivational", enabled: true },
+ // Encouraging messages
+ { id: 6, text: "Your dedication to gooning is impressive!", category: "encouraging", enabled: true },
+ { id: 7, text: "Look how much porn you can handle now!", category: "encouraging", enabled: true },
+ { id: 8, text: "You're building incredible porn tolerance!", category: "encouraging", enabled: true },
+ { id: 9, text: "Accept your place as a beta watcher!", category: "encouraging", enabled: true },
+ { id: 10, text: "Your future is endless gooning sessions!", category: "encouraging", enabled: true },
+ // Achievement messages
+ { id: 11, text: "Excellent edging performance!", category: "achievement", enabled: true },
+ { id: 12, text: "You're such a dedicated gooner!", category: "achievement", enabled: true },
+ { id: 13, text: "Another victory for porn addiction!", category: "achievement", enabled: true },
+ { id: 14, text: "Perfect submission!", category: "achievement", enabled: true },
+ { id: 15, text: "You're mastering the art of denial!", category: "achievement", enabled: true },
+ // Persistence messages
+ { id: 16, text: "Don't stop gooning now - embrace it!", category: "persistence", enabled: true },
+ { id: 17, text: "Every stroke makes you weaker!", category: "persistence", enabled: true },
+ { id: 18, text: "Push deeper into submission!", category: "persistence", enabled: true },
+ { id: 19, text: "You belong on your knees watching!", category: "persistence", enabled: true },
+ { id: 20, text: "True submission is forged through endless edging!", category: "persistence", enabled: true }
+ ];
+ }
+
+ // Calculate statistics
+ const totalMessages = allMessages.length;
+ const enabledMessages = allMessages.filter(msg => msg.enabled !== false).length;
+ const disabledMessages = totalMessages - enabledMessages;
+
+ const categories = {};
+ allMessages.forEach(msg => {
+ const cat = msg.category || 'custom';
+ categories[cat] = (categories[cat] || 0) + 1;
+ });
+
+ // Update statistics display
+ messageStats.innerHTML = `
+
+ Total Messages: ${totalMessages}
+ Enabled: ${enabledMessages}
+ Disabled: ${disabledMessages}
+
+
+ Categories: ${Object.keys(categories).map(cat => `${cat} (${categories[cat]})`).join(', ')}
+
+ `;
+
+ // Generate message list HTML
+ messageList.innerHTML = allMessages.map(msg => `
+
+
+
${msg.text}
+
+ ${msg.category || 'custom'}
+ ID: ${msg.id}
+
+
+
+
+
+
+
+
+ `).join('');
+ }
+
+ function addNewMessage() {
+ const messageText = document.getElementById('new-message-text').value.trim();
+ const category = document.getElementById('message-category').value;
+ const priority = document.getElementById('message-priority').value;
+
+ if (!messageText) {
+ alert('Please enter a message text');
+ return;
+ }
+
+ if (messageText.length > 200) {
+ alert('Message text must be 200 characters or less');
+ return;
+ }
+
+ // Get existing messages or defaults
+ let allMessages = JSON.parse(localStorage.getItem('customFlashMessages') || 'null');
+ if (!allMessages) {
+ allMessages = getDefaultMessages();
+ }
+
+ // Create new message
+ const newMessage = {
+ id: Date.now() + Math.floor(Math.random() * 1000),
+ text: messageText,
+ category: category || 'custom',
+ priority: priority || 'normal',
+ enabled: true,
+ isCustom: true,
+ createdAt: new Date().toISOString()
+ };
+
+ // Add to messages array
+ allMessages.push(newMessage);
+
+ // Save to localStorage
+ localStorage.setItem('customFlashMessages', JSON.stringify(allMessages));
+
+ console.log('Added new message:', newMessage);
+
+ // Clear form
+ document.getElementById('new-message-text').value = '';
+ updateCharCount();
+
+ // Reload message list
+ loadExistingMessages();
+
+ alert('Message added successfully!');
+ }
+
+ function previewMessage() {
+ const messageText = document.getElementById('new-message-text').value.trim();
+ if (!messageText) {
+ alert('Please enter a message text to preview');
+ return;
+ }
+
+ // Create a temporary preview overlay
+ showPreviewMessage(messageText);
+ }
+
+ function testFlashMessage() {
+ // Get a random enabled message for testing
+ let allMessages = JSON.parse(localStorage.getItem('customFlashMessages') || 'null');
+ if (!allMessages) {
+ allMessages = getDefaultMessages();
+ }
+
+ const enabledMessages = allMessages.filter(msg => msg.enabled !== false);
+ if (enabledMessages.length === 0) {
+ alert('No enabled messages to test!');
+ return;
+ }
+
+ const randomMessage = enabledMessages[Math.floor(Math.random() * enabledMessages.length)];
+ showPreviewMessage(randomMessage.text);
+ }
+
+ function testBehaviorSettings() {
+ // TODO: Test behavior settings
+ console.log('Testing behavior settings');
+ }
+
+ // Popup test functions moved to popup image management screen
+
+ function saveAllMessageSettings() {
+ // Save flash message settings
+ const flashSettings = {
+ enabled: document.getElementById('flash-messages-enabled').checked,
+ displayDuration: parseInt(document.getElementById('display-duration').value),
+ intervalDelay: parseInt(document.getElementById('interval-delay').value),
+ timeVariation: parseInt(document.getElementById('time-variation').value),
+ eventBased: document.getElementById('event-based-messages').checked,
+ pauseOnHover: document.getElementById('pause-on-hover').checked
+ };
+
+ // Popup image settings are now managed in separate popup image management screen
+
+ // Save appearance settings
+ const appearanceSettings = {
+ position: document.getElementById('message-position').value,
+ animation: document.getElementById('animation-style').value,
+ fontSize: parseInt(document.getElementById('font-size').value),
+ opacity: parseInt(document.getElementById('message-opacity').value),
+ textColor: document.getElementById('text-color').value,
+ backgroundColor: document.getElementById('background-color').value,
+ removeBackground: document.getElementById('remove-background').checked,
+ textStroke: document.getElementById('text-stroke').checked,
+ strokeColor: document.getElementById('stroke-color').value,
+ strokeWidth: parseInt(document.getElementById('stroke-width').value)
+ };
+
+ console.log('💾 Saving appearance settings:', appearanceSettings);
+
+ // Save to localStorage
+ localStorage.setItem('flashMessageConfig', JSON.stringify(flashSettings));
+ localStorage.setItem('flashMessageAppearance', JSON.stringify(appearanceSettings));
+
+ console.log('✅ Settings saved to localStorage');
+
+ // Update flash message system if it's running
+ if (typeof flashMessageSystem !== 'undefined' && flashMessageSystem) {
+ // Update the config with new appearance settings
+ flashMessageSystem.config = {
+ ...flashMessageSystem.config,
+ ...flashSettings,
+ ...appearanceSettings
+ };
+
+ // Recreate the message element with new styles
+ createFlashMessageElement();
+
+ console.log('✨ Flash message system updated with new appearance settings');
+ }
+
+ console.log('💾 All message settings saved');
+
+ // Debug: Check what was actually saved
+ console.log('🔬 Debug - Checking localStorage after save:');
+ console.log('flashMessageAppearance:', localStorage.getItem('flashMessageAppearance'));
+
+ alert('Message settings saved successfully!');
+ }
+
+ // Debug function - can be called from browser console
+ window.debugAppearanceSettings = function() {
+ console.log('🔬 DEBUG: Current localStorage appearance settings:');
+ const stored = localStorage.getItem('flashMessageAppearance');
+ console.log('Raw:', stored);
+ if (stored) {
+ console.log('Parsed:', JSON.parse(stored));
+ }
+
+ console.log('🔬 DEBUG: Current form values:');
+ console.log('text-color:', document.getElementById('text-color').value);
+ console.log('background-color:', document.getElementById('background-color').value);
+ console.log('font-size:', document.getElementById('font-size').value);
+ console.log('opacity:', document.getElementById('message-opacity').value);
+
+ console.log('🔬 DEBUG: Current flashMessageSystem config:');
+ if (typeof flashMessageSystem !== 'undefined' && flashMessageSystem) {
+ console.log('flashMessageSystem.config:', flashMessageSystem.config);
+ } else {
+ console.log('flashMessageSystem not available');
+ }
+ };
+
+ function resetAppearanceSettings() {
+ document.getElementById('message-position').value = 'center';
+ document.getElementById('animation-style').value = 'fade';
+ document.getElementById('font-size').value = 24;
+ document.getElementById('message-opacity').value = 90;
+ document.getElementById('text-color').value = '#ffffff';
+ document.getElementById('background-color').value = '#007bff';
+ document.getElementById('remove-background').checked = false;
+ document.getElementById('text-stroke').checked = false;
+ document.getElementById('stroke-color').value = '#000000';
+ document.getElementById('stroke-width').value = 2;
+ updateAppearanceDisplays();
+ toggleStrokeOptions();
+ }
+
+ function previewAppearanceSettings() {
+ // TODO: Preview appearance settings
+ console.log('Previewing appearance settings');
+ }
+
+ // Popup Image Management Functions
+ function loadPopupImageSettingsMain() {
+ // Load popup image settings from localStorage or defaults
+ const popupSettings = JSON.parse(localStorage.getItem('popupImageConfig') || '{}');
+
+ // Apply settings to UI elements (using -main suffix for the new screen)
+ document.getElementById('popup-images-enabled-main').checked = popupSettings.enabled !== false;
+ document.getElementById('popup-frequency-main').value = popupSettings.frequency || 'medium';
+ document.getElementById('popup-min-interval-main').value = popupSettings.minInterval || 30;
+ document.getElementById('popup-max-interval-main').value = popupSettings.maxInterval || 120;
+ document.getElementById('popup-count-mode-main').value = popupSettings.countMode || 'fixed';
+ document.getElementById('popup-image-count-main').value = popupSettings.imageCount || 3;
+ document.getElementById('popup-min-count-main').value = popupSettings.minCount || 2;
+ document.getElementById('popup-max-count-main').value = popupSettings.maxCount || 5;
+ document.getElementById('popup-duration-mode-main').value = popupSettings.durationMode || 'fixed';
+ document.getElementById('popup-display-duration-main').value = popupSettings.displayDuration || 8;
+ document.getElementById('popup-min-duration-main').value = popupSettings.minDuration || 5;
+ document.getElementById('popup-max-duration-main').value = popupSettings.maxDuration || 15;
+ document.getElementById('popup-positioning-main').value = popupSettings.positioning || 'random';
+ document.getElementById('popup-allow-overlap-main').checked = popupSettings.allowOverlap || false;
+ document.getElementById('popup-viewport-width-main').value = popupSettings.viewportWidth || 35;
+ document.getElementById('popup-viewport-height-main').value = popupSettings.viewportHeight || 40;
+ document.getElementById('popup-min-width-main').value = popupSettings.minWidth || 200;
+ document.getElementById('popup-max-width-main').value = popupSettings.maxWidth || 500;
+ document.getElementById('popup-min-height-main').value = popupSettings.minHeight || 150;
+ document.getElementById('popup-max-height-main').value = popupSettings.maxHeight || 400;
+ document.getElementById('popup-fade-animation-main').checked = popupSettings.fadeAnimation || false;
+ document.getElementById('popup-blur-background-main').checked = popupSettings.blurBackground || false;
+ document.getElementById('popup-show-timer-main').checked = popupSettings.showTimer || false;
+ document.getElementById('popup-prevent-close-main').checked = popupSettings.preventClose || false;
+
+ // Update display values and visibility
+ updatePopupImageDisplays();
+ updatePopupCountModeMain();
+ updatePopupDurationModeMain();
+ }
+
+ function setupPopupImageManagementEventListeners() {
+ // Range slider listeners for real-time updates
+ document.getElementById('popup-image-count-main').addEventListener('input', updatePopupImageDisplays);
+ document.getElementById('popup-display-duration-main').addEventListener('input', updatePopupImageDisplays);
+ document.getElementById('popup-viewport-width-main').addEventListener('input', updatePopupImageDisplays);
+ document.getElementById('popup-viewport-height-main').addEventListener('input', updatePopupImageDisplays);
+
+ // Frequency listeners
+ document.getElementById('popup-frequency-main').addEventListener('change', updateFrequencySettings);
+ document.getElementById('popup-min-interval-main').addEventListener('input', updatePopupImageDisplays);
+ document.getElementById('popup-max-interval-main').addEventListener('input', updatePopupImageDisplays);
+
+ // Mode change listeners
+ document.getElementById('popup-count-mode-main').addEventListener('change', updatePopupCountModeMain);
+ document.getElementById('popup-duration-mode-main').addEventListener('change', updatePopupDurationModeMain);
+
+ // Test button listeners
+ document.getElementById('test-popup-single-main').addEventListener('click', () => testPopupImages(1));
+ document.getElementById('test-popup-multiple-main').addEventListener('click', testPopupImagesMultiple);
+ document.getElementById('clear-all-popups-main').addEventListener('click', clearAllPopups);
+
+ // Save button listener
+ document.getElementById('save-popup-settings-btn').addEventListener('click', savePopupImageSettings);
+ }
+
+ function updatePopupImageDisplays() {
+ // Update display values for ranges
+ const imageCount = document.getElementById('popup-image-count-main').value;
+ const displayDuration = document.getElementById('popup-display-duration-main').value;
+ const viewportWidth = document.getElementById('popup-viewport-width-main').value;
+ const viewportHeight = document.getElementById('popup-viewport-height-main').value;
+
+ document.getElementById('popup-image-count-value-main').textContent = imageCount;
+ document.getElementById('popup-display-duration-value-main').textContent = displayDuration + 's';
+ document.getElementById('popup-viewport-width-value-main').textContent = viewportWidth + '%';
+ document.getElementById('popup-viewport-height-value-main').textContent = viewportHeight + '%';
+
+ // Show warning for high counts
+ const warning = document.getElementById('popup-warning-main');
+ if (imageCount > 20) {
+ warning.style.display = 'block';
+ } else {
+ warning.style.display = 'none';
+ }
+ }
+
+ function updatePopupCountModeMain() {
+ const mode = document.getElementById('popup-count-mode-main').value;
+ const fixedCount = document.getElementById('popup-fixed-count-main');
+ const rangeCount = document.getElementById('popup-range-count-main');
+
+ if (mode === 'fixed') {
+ fixedCount.style.display = 'block';
+ rangeCount.style.display = 'none';
+ } else if (mode === 'range') {
+ fixedCount.style.display = 'none';
+ rangeCount.style.display = 'block';
+ } else {
+ fixedCount.style.display = 'none';
+ rangeCount.style.display = 'none';
+ }
+ }
+
+ function updatePopupDurationModeMain() {
+ const mode = document.getElementById('popup-duration-mode-main').value;
+ const fixedDuration = document.getElementById('popup-fixed-duration-main');
+ const rangeDuration = document.getElementById('popup-range-duration-main');
+
+ if (mode === 'fixed') {
+ fixedDuration.style.display = 'block';
+ rangeDuration.style.display = 'none';
+ } else if (mode === 'range') {
+ fixedDuration.style.display = 'none';
+ rangeDuration.style.display = 'block';
+ } else {
+ fixedDuration.style.display = 'none';
+ rangeDuration.style.display = 'none';
+ }
+ }
+
+ function updateFrequencySettings() {
+ const frequency = document.getElementById('popup-frequency-main').value;
+ const minInterval = document.getElementById('popup-min-interval-main');
+ const maxInterval = document.getElementById('popup-max-interval-main');
+
+ // Update interval inputs based on frequency selection
+ switch (frequency) {
+ case 'low':
+ minInterval.value = 180; // 3 minutes
+ maxInterval.value = 300; // 5 minutes
+ break;
+ case 'medium':
+ minInterval.value = 120; // 2 minutes
+ maxInterval.value = 180; // 3 minutes
+ break;
+ case 'high':
+ minInterval.value = 60; // 1 minute
+ maxInterval.value = 120; // 2 minutes
+ break;
+ case 'constant':
+ minInterval.value = 30; // 30 seconds
+ maxInterval.value = 60; // 1 minute
+ break;
+ }
+ }
+
+ function testPopupImagesMultiple() {
+ const countMode = document.getElementById('popup-count-mode-main').value;
+ let count;
+
+ if (countMode === 'fixed') {
+ count = parseInt(document.getElementById('popup-image-count-main').value);
+ } else if (countMode === 'random') {
+ count = Math.floor(Math.random() * 10) + 1;
+ } else if (countMode === 'range') {
+ const min = parseInt(document.getElementById('popup-min-count-main').value);
+ const max = parseInt(document.getElementById('popup-max-count-main').value);
+ count = Math.floor(Math.random() * (max - min + 1)) + min;
+ }
+
+ testPopupImages(count);
+ }
+
+ function testPopupImages(count) {
+ if (gameInstance && gameInstance.popupImageManager) {
+ // Apply current settings to the popup manager
+ savePopupImageSettings();
+
+ // Test with the specified count using the periodic popup system
+ for (let i = 0; i < count; i++) {
+ setTimeout(() => {
+ gameInstance.popupImageManager.showPeriodicPopup();
+ }, i * 200); // Stagger the popups slightly
+ }
+ } else {
+ alert('Popup image system not available. Please start the game first.');
+ }
+ }
+
+ function clearAllPopups() {
+ if (gameInstance && gameInstance.popupImageManager) {
+ // Clear periodic popups by hiding any active ones
+ const periodicPopups = document.querySelectorAll('.periodic-popup-container');
+ periodicPopups.forEach(popup => {
+ gameInstance.popupImageManager.hidePeriodicPopup(popup);
+ });
+ }
+ }
+
+ function savePopupImageSettings() {
+ const settings = {
+ enabled: document.getElementById('popup-images-enabled-main').checked,
+ frequency: document.getElementById('popup-frequency-main').value,
+ minInterval: parseInt(document.getElementById('popup-min-interval-main').value),
+ maxInterval: parseInt(document.getElementById('popup-max-interval-main').value),
+ countMode: document.getElementById('popup-count-mode-main').value,
+ imageCount: parseInt(document.getElementById('popup-image-count-main').value),
+ minCount: parseInt(document.getElementById('popup-min-count-main').value),
+ maxCount: parseInt(document.getElementById('popup-max-count-main').value),
+ durationMode: document.getElementById('popup-duration-mode-main').value,
+ displayDuration: parseInt(document.getElementById('popup-display-duration-main').value),
+ minDuration: parseInt(document.getElementById('popup-min-duration-main').value),
+ maxDuration: parseInt(document.getElementById('popup-max-duration-main').value),
+ positioning: document.getElementById('popup-positioning-main').value,
+ allowOverlap: document.getElementById('popup-allow-overlap-main').checked,
+ viewportWidth: parseInt(document.getElementById('popup-viewport-width-main').value),
+ viewportHeight: parseInt(document.getElementById('popup-viewport-height-main').value),
+ minWidth: parseInt(document.getElementById('popup-min-width-main').value),
+ maxWidth: parseInt(document.getElementById('popup-max-width-main').value),
+ minHeight: parseInt(document.getElementById('popup-min-height-main').value),
+ maxHeight: parseInt(document.getElementById('popup-max-height-main').value),
+ fadeAnimation: document.getElementById('popup-fade-animation-main').checked,
+ blurBackground: document.getElementById('popup-blur-background-main').checked,
+ showTimer: document.getElementById('popup-show-timer-main').checked,
+ preventClose: document.getElementById('popup-prevent-close-main').checked
+ };
+
+ localStorage.setItem('popupImageConfig', JSON.stringify(settings));
+
+ // Update the status display
+ document.getElementById('popup-settings-updated-main').textContent = new Date().toLocaleString();
+
+ // Apply settings to game if running
+ if (gameInstance && gameInstance.popupImageManager) {
+ gameInstance.popupImageManager.updateConfig(settings);
+ gameInstance.popupImageManager.updatePeriodicSettings({
+ minInterval: settings.minInterval,
+ maxInterval: settings.maxInterval,
+ displayDuration: settings.displayDuration
+ });
+ }
+
+ // Update available images count
+ updateAvailableImagesCount();
+
+ console.log('🖼️ Popup image settings saved:', settings);
+ alert('Popup image settings saved successfully!');
+ }
+
+ async function updateAvailableImagesCount() {
+ if (gameInstance && gameInstance.popupImageManager) {
+ try {
+ const images = await gameInstance.popupImageManager.getLinkedImages();
+ document.getElementById('available-images-count-main').textContent = images.length;
+ } catch (error) {
+ console.error('Error getting available images count:', error);
+ document.getElementById('available-images-count-main').textContent = '0';
+ }
+ }
+ }
+
+ function exportMessages(type) {
+ // TODO: Export messages functionality
+ console.log('Exporting messages:', type);
+ }
+
+ function importMessages() {
+ document.getElementById('import-messages-file').click();
+ }
+
+ function resetToDefaults() {
+ if (confirm('Reset all messages to defaults? This cannot be undone.')) {
+ localStorage.removeItem('customFlashMessages');
+ loadExistingMessages();
+ console.log('Reset to default messages');
+ alert('Messages reset to defaults!');
+ }
+ }
+
+ function toggleMessageEnabled(messageId) {
+ let allMessages = JSON.parse(localStorage.getItem('customFlashMessages') || 'null');
+
+ // If no custom messages, get defaults first
+ if (!allMessages) {
+ allMessages = getDefaultMessages();
+ }
+
+ const messageIndex = allMessages.findIndex(msg => msg.id === messageId);
+ if (messageIndex !== -1) {
+ allMessages[messageIndex].enabled = !allMessages[messageIndex].enabled;
+ localStorage.setItem('customFlashMessages', JSON.stringify(allMessages));
+ loadExistingMessages();
+ }
+ }
+
+ function editMessage(messageId) {
+ let allMessages = JSON.parse(localStorage.getItem('customFlashMessages') || 'null');
+
+ if (!allMessages) {
+ allMessages = getDefaultMessages();
+ }
+
+ const message = allMessages.find(msg => msg.id === messageId);
+ if (message) {
+ const newText = prompt('Edit message text:', message.text);
+ if (newText !== null && newText.trim() !== '') {
+ message.text = newText.trim();
+ localStorage.setItem('customFlashMessages', JSON.stringify(allMessages));
+ loadExistingMessages();
+ }
+ }
+ }
+
+ function deleteMessage(messageId) {
+ if (confirm('Delete this message? This cannot be undone.')) {
+ let allMessages = JSON.parse(localStorage.getItem('customFlashMessages') || 'null');
+
+ if (!allMessages) {
+ allMessages = getDefaultMessages();
+ }
+
+ const filteredMessages = allMessages.filter(msg => msg.id !== messageId);
+ localStorage.setItem('customFlashMessages', JSON.stringify(filteredMessages));
+ loadExistingMessages();
+ }
+ }
+
+ function getDefaultMessages() {
+ return [
+ // Motivational messages
+ { id: 1, text: "Good goon! Keep stroking and watching!", category: "motivational", enabled: true },
+ { id: 2, text: "Every edge makes you more submissive!", category: "motivational", enabled: true },
+ { id: 3, text: "Porn is your new reality!", category: "motivational", enabled: true },
+ { id: 4, text: "You're becoming such a good little gooner!", category: "motivational", enabled: true },
+ { id: 5, text: "Real men fuck while you watch!", category: "motivational", enabled: true },
+ // Encouraging messages
+ { id: 6, text: "Your dedication to gooning is impressive!", category: "encouraging", enabled: true },
+ { id: 7, text: "Look how much porn you can handle now!", category: "encouraging", enabled: true },
+ { id: 8, text: "You're building incredible porn tolerance!", category: "encouraging", enabled: true },
+ { id: 9, text: "Accept your place as a beta watcher!", category: "encouraging", enabled: true },
+ { id: 10, text: "Your future is endless gooning sessions!", category: "encouraging", enabled: true },
+ // Achievement messages
+ { id: 11, text: "Excellent edging performance!", category: "achievement", enabled: true },
+ { id: 12, text: "You're such a dedicated gooner!", category: "achievement", enabled: true },
+ { id: 13, text: "Another victory for porn addiction!", category: "achievement", enabled: true },
+ { id: 14, text: "Perfect submission!", category: "achievement", enabled: true },
+ { id: 15, text: "You're mastering the art of denial!", category: "achievement", enabled: true },
+ // Persistence messages
+ { id: 16, text: "Don't stop gooning now - embrace it!", category: "persistence", enabled: true },
+ { id: 17, text: "Every stroke makes you weaker!", category: "persistence", enabled: true },
+ { id: 18, text: "Push deeper into submission!", category: "persistence", enabled: true },
+ { id: 19, text: "You belong on your knees watching!", category: "persistence", enabled: true },
+ { id: 20, text: "True submission is forged through endless edging!", category: "persistence", enabled: true }
+ ];
+ }
+
+ function showPreviewMessage(messageText) {
+ // Create preview overlay
+ const overlay = document.createElement('div');
+ overlay.id = 'message-preview-overlay';
+ overlay.style.cssText = `
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(0, 0, 0, 0.7);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ z-index: 10001;
+ backdrop-filter: blur(5px);
+ `;
+
+ // Create message element with current settings
+ const messageElement = document.createElement('div');
+ const position = document.getElementById('message-position').value || 'center';
+ const animation = document.getElementById('animation-style').value || 'fade';
+ const fontSize = document.getElementById('font-size').value || 24;
+ const opacity = document.getElementById('message-opacity').value || 90;
+ const textColor = document.getElementById('text-color').value || '#ffffff';
+ const backgroundColor = document.getElementById('background-color').value || '#007bff';
+ const removeBackground = document.getElementById('remove-background').checked;
+ const textStroke = document.getElementById('text-stroke').checked;
+ const strokeColor = document.getElementById('stroke-color').value || '#000000';
+ const strokeWidth = document.getElementById('stroke-width').value || 2;
+
+ messageElement.textContent = messageText;
+
+ // Build CSS styles
+ let cssStyles = `
+ position: absolute;
+ color: ${textColor};
+ font-size: ${fontSize}px;
+ font-weight: bold;
+ padding: 20px 30px;
+ max-width: 400px;
+ text-align: center;
+ word-wrap: break-word;
+ opacity: ${opacity / 100};
+ `;
+
+ // Add background or remove it
+ if (removeBackground) {
+ cssStyles += `
+ background: transparent;
+ box-shadow: none;
+ border: none;
+ `;
+ } else {
+ cssStyles += `
+ background: ${backgroundColor};
+ border-radius: 15px;
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
+ border: 2px solid rgba(255, 255, 255, 0.2);
+ `;
+ }
+
+ // Add text stroke if enabled
+ if (textStroke) {
+ cssStyles += `
+ text-shadow:
+ -${strokeWidth}px -${strokeWidth}px 0 ${strokeColor},
+ ${strokeWidth}px -${strokeWidth}px 0 ${strokeColor},
+ -${strokeWidth}px ${strokeWidth}px 0 ${strokeColor},
+ ${strokeWidth}px ${strokeWidth}px 0 ${strokeColor};
+ `;
+ }
+
+ messageElement.style.cssText = cssStyles;
+
+ // Position the message
+ switch (position) {
+ case 'top-left':
+ messageElement.style.top = '50px';
+ messageElement.style.left = '50px';
+ break;
+ case 'top-center':
+ messageElement.style.top = '50px';
+ messageElement.style.left = '50%';
+ messageElement.style.transform = 'translateX(-50%)';
+ break;
+ case 'top-right':
+ messageElement.style.top = '50px';
+ messageElement.style.right = '50px';
+ break;
+ case 'center-left':
+ messageElement.style.top = '50%';
+ messageElement.style.left = '50px';
+ messageElement.style.transform = 'translateY(-50%)';
+ break;
+ case 'center':
+ default:
+ messageElement.style.top = '50%';
+ messageElement.style.left = '50%';
+ messageElement.style.transform = 'translate(-50%, -50%)';
+ break;
+ case 'center-right':
+ messageElement.style.top = '50%';
+ messageElement.style.right = '50px';
+ messageElement.style.transform = 'translateY(-50%)';
+ break;
+ case 'bottom-left':
+ messageElement.style.bottom = '50px';
+ messageElement.style.left = '50px';
+ break;
+ case 'bottom-center':
+ messageElement.style.bottom = '50px';
+ messageElement.style.left = '50%';
+ messageElement.style.transform = 'translateX(-50%)';
+ break;
+ case 'bottom-right':
+ messageElement.style.bottom = '50px';
+ messageElement.style.right = '50px';
+ break;
+ }
+
+ overlay.appendChild(messageElement);
+ document.body.appendChild(overlay);
+
+ // Apply animation
+ if (animation === 'slide') {
+ messageElement.style.opacity = '0';
+ messageElement.style.transform += ' translateY(50px)';
+ setTimeout(() => {
+ messageElement.style.transition = 'all 0.5s ease';
+ messageElement.style.opacity = opacity / 100;
+ messageElement.style.transform = messageElement.style.transform.replace('translateY(50px)', '');
+ }, 50);
+ } else if (animation === 'bounce') {
+ messageElement.style.animation = 'flashBounceIn 0.6s ease-out';
+ } else if (animation === 'pulse') {
+ messageElement.style.animation = 'flashPulseIn 0.8s ease-out';
+ }
+
+ // Close on click
+ overlay.addEventListener('click', () => {
+ document.body.removeChild(overlay);
+ });
+
+ // Auto-close after duration
+ const duration = document.getElementById('display-duration').value || 3000;
+ setTimeout(() => {
+ if (document.body.contains(overlay)) {
+ document.body.removeChild(overlay);
+ }
+ }, parseInt(duration));
+ }
+
+ // ===== FLASH MESSAGE SYSTEM FOR QUICK PLAY =====
+
+ let flashMessageSystem = null;
+ let flashMessageTimeout = null;
+
+ function initializeFlashMessages() {
+ // Check if flash messages are enabled
+ const flashSettings = JSON.parse(localStorage.getItem('flashMessageConfig') || '{}');
+ const isEnabled = flashSettings.enabled !== false;
+
+ if (!isEnabled) {
+ console.log('💬 Flash messages disabled');
+ return;
+ }
+
+ // Get messages
+ let allMessages = JSON.parse(localStorage.getItem('customFlashMessages') || 'null');
+ if (!allMessages) {
+ allMessages = getDefaultMessages();
+ }
+
+ const enabledMessages = allMessages.filter(msg => msg.enabled !== false);
+ if (enabledMessages.length === 0) {
+ console.log('💬 No enabled flash messages found');
+ return;
+ }
+
+ // Initialize system
+ // Load appearance settings
+ const appearanceSettings = JSON.parse(localStorage.getItem('flashMessageAppearance') || '{}');
+
+ flashMessageSystem = {
+ messages: enabledMessages,
+ config: {
+ enabled: true,
+ displayDuration: flashSettings.displayDuration || 3000,
+ intervalDelay: flashSettings.intervalDelay || 45000,
+ timeVariation: flashSettings.timeVariation || 5000,
+ eventBased: flashSettings.eventBased !== false,
+ pauseOnHover: flashSettings.pauseOnHover || false,
+ // Appearance settings from both sources
+ position: appearanceSettings.position || flashSettings.position || 'center',
+ animation: appearanceSettings.animation || flashSettings.animation || 'fade',
+ fontSize: appearanceSettings.fontSize || flashSettings.fontSize || 24,
+ opacity: appearanceSettings.opacity || flashSettings.opacity || 90,
+ textColor: appearanceSettings.textColor || flashSettings.textColor || '#ffffff',
+ backgroundColor: appearanceSettings.backgroundColor || flashSettings.backgroundColor || '#007bff',
+ // New appearance options
+ removeBackground: appearanceSettings.removeBackground || false,
+ textStroke: appearanceSettings.textStroke || false,
+ strokeColor: appearanceSettings.strokeColor || '#000000',
+ strokeWidth: appearanceSettings.strokeWidth || 2
+ },
+ isActive: false,
+ isPaused: false,
+ currentElement: null,
+ lastMessageIndex: -1
+ };
+
+ // Create message element
+ createFlashMessageElement();
+
+ // Start the system
+ startFlashMessageSystem();
+
+ console.log(`💬 Flash message system initialized with ${enabledMessages.length} messages`);
+ }
+
+ function createFlashMessageElement() {
+ // Remove existing element if any
+ const existing = document.getElementById('quick-play-flash-message');
+ if (existing) {
+ existing.remove();
+ }
+
+ // Create new element
+ const element = document.createElement('div');
+ element.id = 'quick-play-flash-message';
+ // Build CSS styles
+ let cssStyles = `
+ position: fixed;
+ display: none;
+ font-size: ${flashMessageSystem.config.fontSize}px;
+ font-weight: bold;
+ color: ${flashMessageSystem.config.textColor};
+ padding: 20px 30px;
+ max-width: 400px;
+ z-index: 9999;
+ text-align: center;
+ word-wrap: break-word;
+ transition: opacity 0.5s ease-in-out, transform 0.5s ease-in-out;
+ opacity: ${flashMessageSystem.config.opacity / 100};
+ pointer-events: none;
+ `;
+
+ // Add background or remove it
+ if (flashMessageSystem.config.removeBackground) {
+ cssStyles += `
+ background: transparent;
+ backdrop-filter: none;
+ box-shadow: none;
+ border: none;
+ `;
+ } else {
+ cssStyles += `
+ background: ${flashMessageSystem.config.backgroundColor};
+ border-radius: 15px;
+ box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
+ backdrop-filter: blur(5px);
+ border: 2px solid rgba(255, 255, 255, 0.2);
+ `;
+ }
+
+ // Add text stroke if enabled
+ if (flashMessageSystem.config.textStroke) {
+ const strokeWidth = flashMessageSystem.config.strokeWidth;
+ const strokeColor = flashMessageSystem.config.strokeColor;
+ cssStyles += `
+ text-shadow:
+ -${strokeWidth}px -${strokeWidth}px 0 ${strokeColor},
+ ${strokeWidth}px -${strokeWidth}px 0 ${strokeColor},
+ -${strokeWidth}px ${strokeWidth}px 0 ${strokeColor},
+ ${strokeWidth}px ${strokeWidth}px 0 ${strokeColor};
+ `;
+ }
+
+ element.style.cssText = cssStyles;
+
+ // Position the element
+ positionFlashMessage(element);
+
+ // Add hover pause if enabled
+ if (flashMessageSystem.config.pauseOnHover) {
+ element.style.pointerEvents = 'auto';
+ element.addEventListener('mouseenter', () => {
+ if (flashMessageTimeout) {
+ clearTimeout(flashMessageTimeout);
+ }
+ });
+ element.addEventListener('mouseleave', () => {
+ scheduleHideMessage(flashMessageSystem.config.displayDuration);
+ });
+ }
+
+ document.body.appendChild(element);
+ flashMessageSystem.currentElement = element;
+ }
+
+ function positionFlashMessage(element) {
+ // Reset all positioning
+ element.style.top = '';
+ element.style.bottom = '';
+ element.style.left = '';
+ element.style.right = '';
+ element.style.transform = '';
+
+ const position = flashMessageSystem.config.position;
+ switch (position) {
+ case 'top-left':
+ element.style.top = '20px';
+ element.style.left = '20px';
+ break;
+ case 'top-center':
+ element.style.top = '20px';
+ element.style.left = '50%';
+ element.style.transform = 'translateX(-50%)';
+ break;
+ case 'top-right':
+ element.style.top = '20px';
+ element.style.right = '20px';
+ break;
+ case 'center-left':
+ element.style.top = '50%';
+ element.style.left = '20px';
+ element.style.transform = 'translateY(-50%)';
+ break;
+ case 'center':
+ default:
+ element.style.top = '50%';
+ element.style.left = '50%';
+ element.style.transform = 'translate(-50%, -50%)';
+ break;
+ case 'center-right':
+ element.style.top = '50%';
+ element.style.right = '20px';
+ element.style.transform = 'translateY(-50%)';
+ break;
+ case 'bottom-left':
+ element.style.bottom = '20px';
+ element.style.left = '20px';
+ break;
+ case 'bottom-center':
+ element.style.bottom = '20px';
+ element.style.left = '50%';
+ element.style.transform = 'translateX(-50%)';
+ break;
+ case 'bottom-right':
+ element.style.bottom = '20px';
+ element.style.right = '20px';
+ break;
+ }
+ }
+
+ function startFlashMessageSystem() {
+ if (!flashMessageSystem || flashMessageSystem.messages.length === 0) return;
+
+ flashMessageSystem.isActive = true;
+ flashMessageSystem.isPaused = false;
+
+ // Schedule first message
+ scheduleNextFlashMessage();
+
+ console.log('💬 Flash message system started');
+ }
+
+ function scheduleNextFlashMessage() {
+ if (!flashMessageSystem || !flashMessageSystem.isActive || flashMessageSystem.isPaused) return;
+
+ // Calculate delay with variation
+ const baseDelay = flashMessageSystem.config.intervalDelay;
+ const variation = flashMessageSystem.config.timeVariation;
+ const randomVariation = (Math.random() * 2 - 1) * variation; // -variation to +variation
+ const delay = Math.max(baseDelay + randomVariation, 5000); // Minimum 5 seconds
+
+ flashMessageTimeout = setTimeout(() => {
+ showRandomFlashMessage();
+ }, delay);
+ }
+
+ function showRandomFlashMessage() {
+ if (!flashMessageSystem || !flashMessageSystem.isActive || flashMessageSystem.isPaused) return;
+ if (!flashMessageSystem.currentElement || flashMessageSystem.messages.length === 0) return;
+
+ // Pick a random message (avoid repeating the last one if possible)
+ let messageIndex;
+ if (flashMessageSystem.messages.length > 1) {
+ do {
+ messageIndex = Math.floor(Math.random() * flashMessageSystem.messages.length);
+ } while (messageIndex === flashMessageSystem.lastMessageIndex);
+ } else {
+ messageIndex = 0;
+ }
+
+ const message = flashMessageSystem.messages[messageIndex];
+ flashMessageSystem.lastMessageIndex = messageIndex;
+
+ displayFlashMessage(message.text);
+ }
+
+ function displayFlashMessage(messageText) {
+ if (!flashMessageSystem || !flashMessageSystem.currentElement) return;
+
+ console.log('💬 Displaying flash message:', messageText);
+
+ const element = flashMessageSystem.currentElement;
+ element.textContent = messageText;
+ element.style.display = 'block';
+ element.style.opacity = '0';
+
+ // Apply animation
+ requestAnimationFrame(() => {
+ applyFlashAnimation(element, 'show');
+ });
+
+ // Schedule hide
+ scheduleHideMessage(flashMessageSystem.config.displayDuration);
+ }
+
+ function scheduleHideMessage(delay) {
+ flashMessageTimeout = setTimeout(() => {
+ hideFlashMessage();
+ }, delay);
+ }
+
+ function hideFlashMessage() {
+ if (!flashMessageSystem || !flashMessageSystem.currentElement) return;
+
+ const element = flashMessageSystem.currentElement;
+ applyFlashAnimation(element, 'hide');
+
+ setTimeout(() => {
+ element.style.display = 'none';
+ // Schedule next message
+ scheduleNextFlashMessage();
+ }, 500);
+ }
+
+ function applyFlashAnimation(element, type) {
+ const animation = flashMessageSystem.config.animation;
+ const opacity = flashMessageSystem.config.opacity / 100;
+
+ if (type === 'show') {
+ switch (animation) {
+ case 'slide':
+ element.style.transform += ' translateY(50px)';
+ element.style.opacity = '0';
+ setTimeout(() => {
+ element.style.transition = 'all 0.5s ease';
+ element.style.opacity = opacity;
+ element.style.transform = element.style.transform.replace('translateY(50px)', '');
+ }, 50);
+ break;
+ case 'bounce':
+ element.style.opacity = opacity;
+ element.style.animation = 'flashBounceIn 0.6s ease-out';
+ break;
+ case 'pulse':
+ element.style.opacity = opacity;
+ element.style.animation = 'flashPulseIn 0.8s ease-out';
+ break;
+ case 'fade':
+ default:
+ element.style.opacity = opacity;
+ break;
+ }
+ } else if (type === 'hide') {
+ switch (animation) {
+ case 'slide':
+ element.style.transform += ' translateY(-50px)';
+ element.style.opacity = '0';
+ break;
+ case 'bounce':
+ case 'pulse':
+ element.style.animation = 'flashFadeOut 0.5s ease-in';
+ break;
+ case 'fade':
+ default:
+ element.style.opacity = '0';
+ break;
+ }
+ }
+ }
+
+ function stopFlashMessageSystem() {
+ if (!flashMessageSystem) return;
+
+ flashMessageSystem.isActive = false;
+ flashMessageSystem.isPaused = true;
+
+ if (flashMessageTimeout) {
+ clearTimeout(flashMessageTimeout);
+ flashMessageTimeout = null;
+ }
+
+ if (flashMessageSystem.currentElement) {
+ flashMessageSystem.currentElement.style.display = 'none';
+ }
+
+ console.log('💬 Flash message system stopped');
+ }
+
+ function pauseFlashMessageSystem() {
+ if (!flashMessageSystem) return;
+
+ flashMessageSystem.isPaused = true;
+
+ if (flashMessageTimeout) {
+ clearTimeout(flashMessageTimeout);
+ flashMessageTimeout = null;
+ }
+
+ console.log('💬 Flash message system paused');
+ }
+
+ function resumeFlashMessageSystem() {
+ if (!flashMessageSystem || !flashMessageSystem.isActive) return;
+
+ flashMessageSystem.isPaused = false;
+ scheduleNextFlashMessage();
+
+ console.log('💬 Flash message system resumed');
+ }
+
+ // Trigger event-based messages
+ function triggerEventFlashMessage(eventType) {
+ if (!flashMessageSystem || !flashMessageSystem.config.eventBased) return;
+
+ // Find messages for specific event types
+ let eventMessages = [];
+ switch (eventType) {
+ case 'taskComplete':
+ eventMessages = flashMessageSystem.messages.filter(msg => msg.category === 'achievement');
+ break;
+ case 'taskSkip':
+ eventMessages = flashMessageSystem.messages.filter(msg => msg.category === 'persistence');
+ break;
+ case 'gameStart':
+ eventMessages = flashMessageSystem.messages.filter(msg => msg.category === 'motivational');
+ break;
+ case 'streak':
+ eventMessages = flashMessageSystem.messages.filter(msg => msg.category === 'achievement');
+ break;
+ default:
+ eventMessages = flashMessageSystem.messages.filter(msg => msg.category === 'encouraging');
+ break;
+ }
+
+ if (eventMessages.length === 0) {
+ // Fallback to any available message
+ eventMessages = flashMessageSystem.messages;
+ }
+
+ if (eventMessages.length > 0) {
+ const randomMessage = eventMessages[Math.floor(Math.random() * eventMessages.length)];
+
+ // Clear current schedule temporarily
+ if (flashMessageTimeout) {
+ clearTimeout(flashMessageTimeout);
+ flashMessageTimeout = null;
+ }
+
+ displayFlashMessage(randomMessage.text);
+ }
+ }