From c04d698951b34268905637faba42e98dade88055 Mon Sep 17 00:00:00 2001 From: SKProCH Date: Wed, 8 Oct 2025 14:08:30 +0300 Subject: [PATCH] Improve storage handling for progress data; add fallback for quota limits by stripping pixel data and retrying. --- Extension/scripts/Acc-Switch.js | 45 +++++++++++++++++++++++-- Extension/scripts/Auto-Image.js | 54 ++++++++++++++++++++++++++---- Extension/scripts/utils-manager.js | 44 ++++++++++++++++++++++-- 3 files changed, 131 insertions(+), 12 deletions(-) diff --git a/Extension/scripts/Acc-Switch.js b/Extension/scripts/Acc-Switch.js index 536e9be..1206ec7 100644 --- a/Extension/scripts/Acc-Switch.js +++ b/Extension/scripts/Acc-Switch.js @@ -2550,8 +2550,37 @@ paintedMapPacked: paintedMapPacked, } - localStorage.setItem("wplace-bot-progress", JSON.stringify(progressData)) - return true + try { + localStorage.setItem("wplace-bot-progress", JSON.stringify(progressData)) + return true + } catch (e) { + // If quota exceeded, strip heavy pixel data and retry + if (progressData && progressData.imageData && progressData.imageData.pixels) { + const slim = { + ...progressData, + imageData: { + width: progressData.imageData.width, + height: progressData.imageData.height, + totalPixels: progressData.imageData.totalPixels, + pixelsStripped: true, + } + }; + try { + localStorage.setItem("wplace-bot-progress", JSON.stringify(slim)) + console.warn('Saved progress without raw pixel data due to storage quota limits.'); + return true + } catch (e2) { + try { + sessionStorage.setItem("wplace-bot-progress", JSON.stringify(slim)) + console.warn('Saved progress to sessionStorage without pixel data due to storage quota limits.'); + return true + } catch (e3) { + throw e2 + } + } + } + throw e + } } catch (error) { console.error("Error saving progress:", error) return false @@ -2602,7 +2631,7 @@ try { Object.assign(state, savedData.state) - if (savedData.imageData) { + if (savedData.imageData && Array.isArray(savedData.imageData.pixels)) { state.imageData = { ...savedData.imageData, pixels: new Uint8ClampedArray(savedData.imageData.pixels), @@ -2624,6 +2653,16 @@ console.warn('Could not rebuild processor from saved image data:', e); } } + else if (savedData.imageData && savedData.imageData.pixelsStripped) { + console.warn('⚠️ Saved progress did not include raw pixel data due to quota limits. Please reload the image to resume.'); + state.imageData = { + width: savedData.imageData.width, + height: savedData.imageData.height, + totalPixels: savedData.imageData.totalPixels, + pixels: null, + }; + state.imageLoaded = false; + } // Prefer packed form if available; fallback to legacy paintedMap array for backward compatibility if (savedData.paintedMapPacked && savedData.paintedMapPacked.data) { diff --git a/Extension/scripts/Auto-Image.js b/Extension/scripts/Auto-Image.js index bd32746..97203b4 100644 --- a/Extension/scripts/Auto-Image.js +++ b/Extension/scripts/Auto-Image.js @@ -1375,8 +1375,39 @@ function getText(key, params) { window.globalUtilsManager.buildPaintedMapPacked() : null }; - localStorage.setItem('wplace-bot-progress', JSON.stringify(data)); - return true; + // Attempt to save; if payload is too large (QuotaExceeded), retry without heavy pixel data + try { + localStorage.setItem('wplace-bot-progress', JSON.stringify(data)); + return true; + } catch (e) { + // Fallback: strip image pixels to reduce size and retry + if (data && data.imageData && data.imageData.pixels) { + const slimData = { + ...data, + imageData: { + width: data.imageData.width, + height: data.imageData.height, + totalPixels: data.imageData.totalPixels, + pixelsStripped: true, + } + }; + try { + localStorage.setItem('wplace-bot-progress', JSON.stringify(slimData)); + console.warn('Saved progress without raw pixel data due to storage quota limits.'); + return true; + } catch (e2) { + try { + // Last resort: try sessionStorage + sessionStorage.setItem('wplace-bot-progress', JSON.stringify(slimData)); + console.warn('Saved progress to sessionStorage without pixel data due to storage quota limits.'); + return true; + } catch (e3) { + throw e2; // will be handled by outer catch + } + } + } + throw e; + } } catch (error) { console.error('Error saving progress:', error); return false; @@ -1432,7 +1463,7 @@ function getText(key, params) { console.log('⚠️ [DEBUG] No availableColors found in savedData or not an array'); } - if (savedData.imageData) { + if (savedData.imageData && Array.isArray(savedData.imageData.pixels)) { console.log('🔍 [DEBUG] Restoring imageData...'); console.log('🔍 [DEBUG] ImageData type check - pixels is array:', Array.isArray(savedData.imageData.pixels)); console.log('🔍 [DEBUG] ImageData pixels length:', savedData.imageData.pixels?.length); @@ -1443,6 +1474,16 @@ function getText(key, params) { }; console.log('✅ [DEBUG] ImageData restored successfully'); console.log('🔍 [DEBUG] Converted pixels to Uint8ClampedArray, length:', window.state.imageData.pixels.length); + } else if (savedData.imageData && savedData.imageData.pixelsStripped) { + console.warn('⚠️ [DEBUG] Saved progress did not include raw pixel data due to quota limits. Please reload the image file to resume.'); + // Preserve dimensions for UI, but mark image as not loaded + window.state.imageData = { + width: savedData.imageData.width, + height: savedData.imageData.height, + totalPixels: savedData.imageData.totalPixels, + pixels: null, + }; + window.state.imageLoaded = false; } else { console.log('⚠️ [DEBUG] No imageData found in savedData'); } @@ -8366,9 +8407,9 @@ function getText(key, params) { } } - // Concatenate all blocks + // Concatenate all blocks (avoid spread on large arrays) for (const block of blocks) { - coords.push(...block); + coords = coords.concat(block); } } else { throw new Error(`Unknown mode: ${mode}`); @@ -8822,7 +8863,8 @@ function getText(key, params) { pixelsToProcess = []; for (let i = startIndex; i < sortedColorGroups.length; i++) { const [colorId, pixels] = sortedColorGroups[i]; - pixelsToProcess.push(...pixels); + // Avoid using spread with very large arrays to prevent call stack overflow + pixelsToProcess = pixelsToProcess.concat(pixels); } console.log(`✅ Prepared ${pixelsToProcess.length} pixels for color-by-color painting`); diff --git a/Extension/scripts/utils-manager.js b/Extension/scripts/utils-manager.js index e0f458a..2d91bd0 100644 --- a/Extension/scripts/utils-manager.js +++ b/Extension/scripts/utils-manager.js @@ -727,8 +727,37 @@ class WPlaceUtilsManager { saveProgress() { try { const progressData = this.buildProgressData(); - localStorage.setItem('wplace-bot-progress', JSON.stringify(progressData)); - return true; + try { + localStorage.setItem('wplace-bot-progress', JSON.stringify(progressData)); + return true; + } catch (e) { + // Strip heavy pixel data and retry if quota exceeded + if (progressData && progressData.imageData && progressData.imageData.pixels) { + const slim = { + ...progressData, + imageData: { + width: progressData.imageData.width, + height: progressData.imageData.height, + totalPixels: progressData.imageData.totalPixels, + pixelsStripped: true, + } + }; + try { + localStorage.setItem('wplace-bot-progress', JSON.stringify(slim)); + console.warn('Saved progress without raw pixel data due to storage quota limits.'); + return true; + } catch (e2) { + try { + sessionStorage.setItem('wplace-bot-progress', JSON.stringify(slim)); + console.warn('Saved progress to sessionStorage without pixel data due to storage quota limits.'); + return true; + } catch (e3) { + throw e2; + } + } + } + throw e; + } } catch (error) { console.error('Error saving progress:', error); return false; @@ -799,7 +828,7 @@ class WPlaceUtilsManager { window.state.colorsChecked = true; // Mark colors as checked } - if (savedData.imageData) { + if (savedData.imageData && Array.isArray(savedData.imageData.pixels)) { window.state.imageData = { width: savedData.imageData.width, height: savedData.imageData.height, @@ -836,6 +865,15 @@ class WPlaceUtilsManager { } catch (e) { console.warn('Could not rebuild processor from saved image data:', e); } + } else if (savedData.imageData && savedData.imageData.pixelsStripped) { + console.warn('⚠️ Saved progress did not include raw pixel data due to quota limits. Please reload the image to resume.'); + window.state.imageData = { + width: savedData.imageData.width, + height: savedData.imageData.height, + totalPixels: savedData.imageData.totalPixels, + pixels: null, + }; + window.state.imageLoaded = false; } // Prefer packed form if available; fallback to legacy paintedMap array for backward compatibility