diff --git a/content.js b/content.js index 04005a8..a8aaa48 100644 --- a/content.js +++ b/content.js @@ -3,12 +3,15 @@ // Log that the content script is running console.log("Content script is running."); +// --- Feature Detection for Cross-Browser Compatibility --- +const runtimeAPI = typeof browser !== 'undefined' ? browser : chrome; +const storageAPI = runtimeAPI.storage; // This will be browser.storage or chrome.storage +// --- Original Font Loading Logic --- let fontLoaded = false; function loadFont() { - return "nuh uh"; - const fontUrl = chrome.runtime.getURL("fonts/fot_rodin_pro_m.ttf"); + const fontUrl = runtimeAPI.runtime.getURL("fonts/fot_rodin_pro_m.ttf"); const style = document.createElement('style'); style.textContent = ` @font-face { @@ -21,30 +24,13 @@ function loadFont() { * { font-family: 'Wii NTLG PGothic JPN Regular', sans-serif !important; } - #text03-01 { + #text03-01, #text05-01, #text06-01 { display: flex; /* Enable flexbox */ justify-content: center; /* Center horizontally */ align-items: center; /* Center vertically */ height: 100vh; /* Full height of the viewport */ width: 100%; /* Full width */ } - - #text05-01 { - display: flex; /* Enable flexbox */ - justify-content: center; /* Center horizontally */ - align-items: center; /* Center vertically */ - height: 100vh; /* Full height of the viewport */ - width: 100%; /* Full width */ - } - - #text06-01 { - display: flex; /* Enable flexbox */ - justify-content: center; /* Center horizontally */ - align-items: center; /* Center vertically */ - height: 100vh; /* Full height of the viewport */ - width: 100%; /* Full width */ - } - .buttonTextBlackM { font-size: 24px; /* Adjust font size as needed */ color: black; /* Set text color */ @@ -52,96 +38,84 @@ function loadFont() { } `; - // Try to append to the head first const head = document.head || document.getElementsByTagName('head')[0]; if (head) { head.appendChild(style); console.log("Font loaded into ."); - return "Font loaded into "; // Return success message + return "Font loaded into "; } - // If head is not available, use MutationObserver to wait for it const observer = new MutationObserver(() => { const head = document.head || document.getElementsByTagName('head')[0]; if (head) { head.appendChild(style); - observer.disconnect(); // Stop observing once the style is added + observer.disconnect(); console.log("Font loaded into via MutationObserver."); - return "Font loaded into via MutationObserver"; // Return success message + return "Font loaded into via MutationObserver"; } }); - - // Start observing the document for changes observer.observe(document, { childList: true, subtree: true }); - // Fallback: If the head is still not available, append to the body const fallbackTimeout = setTimeout(() => { if (!document.head || !document.head.contains(style)) { document.body.appendChild(style); console.log("Font loaded into as a fallback."); - observer.disconnect(); // Stop observing if we fall back - return "Font loaded into as a fallback"; // Return success message + observer.disconnect(); + return "Font loaded into as a fallback"; } - }, 1000); // Wait for 1 second before falling back + }, 1000); - // Check if the observer is still active after 2 seconds setTimeout(() => { - // If the font is still not loaded, log an error if (!document.head || !document.body.contains(style)) { console.error("Failed to load font: and are not available."); - return "Failed to load font: and are not available."; // Return error message + return "Failed to load font: and are not available."; } - observer.disconnect(); // Clear the observer - clearTimeout(fallbackTimeout); // Clear the timeout - }, 2000); // Check again after 2 seconds + observer.disconnect(); + clearTimeout(fallbackTimeout); + }, 2000); - return "Font loading initiated"; // Return initial status + return "Font loading initiated"; } // Check the font state on page load - function checkFontState() { - chrome.storage.local.get(['fontDisabled'], function(result) { + storageAPI.local.get(['fontDisabled']).then(function(result) { if (!result.fontDisabled) { - return "disabled"; - return loadFont(); + loadFont(); // Call loadFont, no need to return its string status here } else { - return "disabled"; + console.log("Font loading disabled by preference."); } - }); + }).catch(error => console.error("Error checking font state:", error)); } -// Define the relative paths to your sound files within the extension + const soundFilePaths = [ - '', // Index 0 (unused) - 'audio/1.wav', - 'audio/2.wav', - 'audio/3.wav', - 'audio/4.wav', - 'audio/5.wav', - 'audio/6.wav', - 'audio/7.wav' + '', // Index 0 (unused) + 'audio/1.wav', + 'audio/2.wav', + 'audio/3.wav', + 'audio/4.wav', + 'audio/5.wav', + 'audio/6.wav', + 'audio/7.wav' ]; +const bgmFilePath = 'audio/bgm.wav'; // Define BGM file path -// Define the path for the BGM file -const bgmFilePath = 'audio/bgm.wav'; // <--- NEW BGM PATH - -const generatedSoundUrls = soundFilePaths.map(path => path ? browser.runtime.getURL(path) : ''); -const generatedBgmUrl = browser.runtime.getURL(bgmFilePath); - -// Function to load class definitions based on the browser -const loadClassDefinitions = async () => { - let classDefinitionsUrl; - const userAgent = navigator.userAgent.toLowerCase(); - - if (userAgent.includes("chrome")) { - classDefinitionsUrl = chrome.runtime.getURL('classDefinitions.js'); - } else if (userAgent.includes("firefox")) { - classDefinitionsUrl = browser.runtime.getURL('classDefinitions.js'); +// Generate the full, web-accessible URLs +const generatedSoundUrls = []; +for (let i = 0; i < soundFilePaths.length; i++) { + if (soundFilePaths[i]) { + generatedSoundUrls[i] = runtimeAPI.runtime.getURL(soundFilePaths[i]); } else { - console.warn("Unsupported browser. Class definitions will not be loaded."); - return; + generatedSoundUrls[i] = ''; } +} +const generatedBgmUrl = runtimeAPI.runtime.getURL(bgmFilePath); // Generate BGM URL + + +// Function to load class definitions and inject globals +const loadClassDefinitions = async () => { + let classDefinitionsUrl = runtimeAPI.runtime.getURL('classDefinitions.js'); try { const response = await fetch(classDefinitionsUrl); @@ -151,31 +125,33 @@ const loadClassDefinitions = async () => { const classDefinitionsText = await response.text(); // Get the current BGM enabled state from storage - // Use browser.storage.local for Firefox compatibility - const storageResult = await browser.storage.local.get(['bgmEnabled']); + const storageResult = await storageAPI.local.get(['bgmEnabled']); const bgmInitiallyEnabled = storageResult.bgmEnabled === true; // Default to false if not set const script = document.createElement('script'); script.setAttribute('type', 'text/javascript'); - // PREPEND the sound URLs, BGM URL, and BGM enabled state as global variables + // PREPEND the sound and BGM URLs as global variables *before* the classDefinitions.js content script.textContent = ` (function() { + // Define global variables that classDefinitions.js can access window._wiiShopSoundUrls_ = ${JSON.stringify(generatedSoundUrls)}; window._wiiShopBgmUrl_ = ${JSON.stringify(generatedBgmUrl)}; - window._wiiShopBgmInitiallyEnabled_ = ${JSON.stringify(bgmInitiallyEnabled)}; // <--- PASS BGM STATE + window._wiiShopBgmInitiallyEnabled_ = ${JSON.stringify(bgmInitiallyEnabled)}; // Pass BGM state })(); - ` + classDefinitionsText; + ` + classDefinitionsText; // Append the actual classDefinitions.js content document.documentElement.insertBefore(script, document.documentElement.firstChild); script.onload = function() { this.remove(); - // Clean up the global variables after classDefinitions.js has used them - delete window._wiiShopSoundUrls_; - delete window._wiiShopBgmUrl_; - delete window._wiiShopBgmInitiallyEnabled_; // <--- CLEAN UP BGM STATE + // Clean up the global variables after classDefinitions.js has likely used them + // These are no longer needed as they are referenced immediately by the injected script. + // delete window._wiiShopSoundUrls_; + // delete window._wiiShopBgmUrl_; + // delete window._wiiShopBgmInitiallyEnabled_; // Clean up BGM state }; + console.log("classDefinitions.js and global URLs injected into page context via script element."); } catch (error) { console.error("Failed to load class definitions:", error); @@ -185,35 +161,58 @@ const loadClassDefinitions = async () => { // Load the class definitions loadClassDefinitions(); // Load the existing trace and points from localStorage -const result = checkFontState(); -console.log(result); +checkFontState(); // Call checkFontState to initiate font loading -browser.runtime.onMessage.addListener((request, sender, sendResponse) => { - if (request.action === "toggleBGM") { - // Here, you'd typically want to call a function on the page - // to control the BGM. Since wiiSound is defined in classDefinitions.js, - // which runs in the page's context, you need to use a custom event - // or directly call window.wiiSound if it's already available. - // For simplicity, let's assume classDefinitions.js has exposed a way to call it. - // Or, we could just re-inject a small script to call it. - const controlScript = document.createElement('script'); - controlScript.textContent = ` - (function() { - if (window.wiiSound && typeof window.wiiSound.currentBgmAudio !== 'undefined') { - if (window.wiiSound.currentBgmAudio) { - window.wiiSound.currentBgmAudio.pause(); - window.wiiSound.currentBgmAudio.currentTime = 0; - } - if (${request.enabled}) { - // Re-instantiate wiiSound to get the latest instance, - // then call playBGM(). This ensures the method exists. - new window.wiiSound().playBGM(); - } - } - })(); - `; - document.documentElement.appendChild(controlScript); - controlScript.onload = function() { this.remove(); }; +// --- Initial BGM Playback on DOMContentLoaded --- +document.addEventListener('DOMContentLoaded', async () => { + // Give a slight delay to ensure classDefinitions.js and window.extensionStorage are fully ready + await new Promise(resolve => setTimeout(resolve, 50)); + + // Request the initial BGM enabled state from the background script via extensionStorage + // We expect extensionStorage to be available after classDefinitions.js is injected + if (typeof window.extensionStorage !== 'undefined' && typeof window.extensionStorage.get === 'function') { + try { + const bgmEnabled = await window.extensionStorage.get('bgmEnabled'); + console.log("Initial BGM enabled state from storage:", bgmEnabled); + + if (bgmEnabled === true) { // Explicitly check for true + console.log("Attempting to play initial BGM from content script."); + // Use the new sendMessageToBackground proxy for BGM control + // This will send a request to /_extension_storage?action=playBGM&bgmUrl=... + window.extensionStorage.sendMessageToBackground({ + action: "playBGM", + bgmUrl: generatedBgmUrl + }); + } + } catch (error) { + console.error("Error retrieving initial BGM state or sending play request:", error); + } + } else { + console.warn("window.extensionStorage not available for initial BGM check."); + } +}); + +// Listener for messages from the popup (if any, specifically for BGM toggle) +runtimeAPI.runtime.onMessage.addListener((request, sender, sendResponse) => { + if (request.action === "toggleBGMImmediate") { + if (request.enabled) { + console.log("Received toggleBGMImmediate from popup: Play BGM."); + // Send a message to background via extensionStorage proxy for consistency + if (typeof window.extensionStorage !== 'undefined' && typeof window.extensionStorage.sendMessageToBackground === 'function') { + window.extensionStorage.sendMessageToBackground({ + action: "playBGM", + bgmUrl: generatedBgmUrl + }); + } + } else { + console.log("Received toggleBGMImmediate from popup: Stop BGM."); + // Send a message to background via extensionStorage proxy for consistency + if (typeof window.extensionStorage !== 'undefined' && typeof window.extensionStorage.sendMessageToBackground === 'function') { + window.extensionStorage.sendMessageToBackground({ + action: "stopBGM" + }); + } + } } }); \ No newline at end of file