1/** 2 * Editor state store â a single mutable object that the gallery editor 3 * and its tool modules read and write directly. 4 * 5 * Migration: galleryEditor.js used to own ~110 module-scope `let` 6 * declarations and capture them via closure. Tool modules can't import 7 * a `let` binding's mutations across module boundaries, so we move the 8 * state into a single exported OBJECT whose properties are freely 9 * mutated by anyone holding a reference. Read/write `state.transformW` 10 * exactly the way the old code wrote `_transformW`. 11 * 12 * Slices land here one tool at a time; this file grows as more state 13 * migrates out of galleryEditor.js. Defaults match the legacy 14 * module-scope initializers verbatim â every `state.foo = â¦` reset 15 * site in galleryEditor.js still works unchanged. 16 */ 17export const state = { 18 // ââ Transform tool ââ 19 // Drag-resize / rotate session state. While `transformActive` is 20 // false every field below should be considered stale. 21 transformActive: false, 22 transformLayer: null, 23 transformOrigW: 0, 24 transformOrigH: 0, 25 // Which corner/edge handle the user is currently dragging. One of 26 // 'tl' | 'tr' | 'bl' | 'br' | 'rot' | null. 27 transformHandle: null, 28 // Which handle is currently under the cursor (no drag). Drives the 29 // hover cursor lookup; lives next to `transformHandle` because both 30 // come from `_getTransformHandle`. 31 hoveredHandle: null, 32 // Snapshot of the layer canvas + offset at transform start so Cancel 33 // can restore exactly without re-fetching from the layer. 34 transformOrigCanvas: null, 35 transformOrigOffset: null, 36 // In-progress dimensions / rotation / flips committed on Apply. 37 transformPendingW: 0, 38 transformPendingH: 0, 39 transformPendingRot: 0, 40 transformPendingFlipH: false, 41 transformPendingFlipV: false, 42 transformAspectLock: true, 43 // Floating Transform popup element + drag-start offsets. 44 transformPopup: null, 45 transformStartX: 0, 46 transformStartY: 0, 47 transformStartOffX: 0, 48 transformStartOffY: 0, 49 // Transform overlay canvas â separate canvas positioned over the 50 // main canvas with extra slack for handle rendering. Created by 51 // _buildEditor; the move/transform tools draw their handle layer 52 // onto its 2D context. 53 transformOverlay: null, 54 transformOverlayCtx: null, 55 56 // ââ Magic Wand tool ââ 57 // Binary selection mask + the layer it was sampled from. `wandMask` 58 // is a canvas the size of `wandLayer`'s pixels, white where selected, 59 // transparent elsewhere. `wandLastSeed` remembers the last click so 60 // tolerance retunes can re-run the flood-fill without re-prompting. 61 wandMask: null, 62 wandLayerId: null, 63 wandTolerance: 24, 64 wandMaskVisible: true, 65 wandMode: 'replace', 66 wandLiveRetune: false, 67 wandLastSeed: null, 68 // Cached layer pixel data (getImageData is O(pixels) â expensive for 69 // 4K layers; invalidated when the active layer changes). 70 wandSrcCache: null, 71 72 // ââ Brush / Eraser / Clone tools ââ 73 // Shared paint color (brush picks up the swatch; eraser and clone 74 // ignore color but reuse the same picker control). 75 color: '#e06c75', 76 // Brush diameter in canvas pixels. Persisted across tool switches; 77 // bumped to a mask-friendly default on first inpaint entry. 78 brushSize: 8, 79 // Per-tool stroke modifiers â opacity + flow + softness. Each tool 80 // owns its own row so users can dial them in independently. 81 brushOpacity: 100, 82 brushFlow: 100, 83 brushSoftness: 100, 84 eraserOpacity: 100, 85 eraserFlow: 100, 86 eraserSoftness: 100, 87 cloneOpacity: 100, 88 cloneFlow: 100, 89 cloneSoftness: 100, 90 // Clone-stamp source point (set via Alt-click or double-tap). Null 91 // means no source picked yet â clicking with the clone tool no-ops 92 // until a source is set. 93 cloneSourceX: null, 94 cloneSourceY: null, 95 // Stroke-start offsets so the source moves WITH the brush, keeping 96 // the sourceâdestination offset constant across the stroke. 97 cloneStrokeStartX: null, 98 cloneStrokeStartY: null, 99 // Frozen snapshot of the source layer's pixels at stroke start so 100 // moving the source over previously-painted pixels samples the 101 // original, not the in-progress stamp ring. 102 cloneSourceSnapshot: null, 103 cloneSourceLayerId: null, 104 // Mobile: double-tap detection for "set source" since Alt-click 105 // isn't an option without a keyboard. 106 cloneLastTapTime: 0, 107 cloneLastTapX: 0, 108 cloneLastTapY: 0, 109 110 // ââ Inpaint + mask ââ 111 // Active mask canvas + its 2D context. Re-pointed to the active 112 // mask sub-layer whenever the user picks a different mask in the 113 // layer panel. 114 maskCanvas: null, 115 maskCtx: null, 116 maskVisible: true, 117 // Reused canvas for the union-of-masks tint pass (saves repeated 118 // allocation on every composite). 119 compositeMaskUnion: null, 120 // Visual tint applied to mask pixels in the composite â purely 121 // cosmetic; the AI model still sees a hard binary mask. 122 maskTintColor: 'rgba(255, 110, 110, 1)', 123 maskTintOpacity: 0.28, 124 // Inpaint-tool paint vs erase modes (Ctrl+Alt flips for a single 125 // stroke; UI buttons toggle the persistent setting). 126 inpaintEraseMode: false, 127 inpaintEraseStroke: false, 128 // First-entry guard: bump brush size to the mask-friendly default 129 // the first time the user opens inpaint per session.
130 inpaintBrushInitialised: false, 131 // Last successful inpaint result layer â drives the live edge 132 // feather / stroke sliders (those only apply to the most recent 133 // result). 134 lastInpaintLayerId: null, 135 // Captured handlers so we can detach them on close without leaking. 136 inpaintDismissHandlers: null, 137 // Background-remove tool state â pristine snapshot so the edge 138 // cleanup sliders can live-rebuild alpha without re-running rembg. 139 rembgLiveLayer: null, 140 rembgLiveSnap: null, 141 // Memoised "is rembg installed on the server?" probe. 142 rembgInstalledCache: null, 143 144 // ââ Stroke drag state ââ 145 // Generic in-progress-stroke flags shared by brush/eraser/clone/ 146 // inpaint. `lastX/Y` are the last mouse position used to interpolate 147 // a continuous line through fast-moving cursor samples. 148 drawing: false, 149 lastX: 0, 150 lastY: 0, 151 152 // ââ Move tool ââ 153 moving: false, 154 moveStartX: 0, 155 moveStartY: 0, 156 // Layer offset at drag start so we can compute the new offset by 157 // (mouse - startMouse) + startOffset rather than accumulating delta. 158 moveLayerOffsetX: 0, 159 moveLayerOffsetY: 0, 160 // Snap guides drawn during a move-tool drag (Ctrl held). Each entry 161 // is a vertical / horizontal line in canvas space. 162 activeSnapGuides: null, 163 164 // ââ Crop tool ââ 165 cropping: false, 166 cropStart: null, 167 cropEnd: null, 168 cropRect: null, 169 cropAspectLock: null, 170 // True while the user drags the inside of an already-finished crop 171 // rect to reposition it. 172 cropMoving: false, 173 cropMoveStart: null, 174 175 // ââ Lasso tool ââ 176 // Freehand selection polygon in canvas pixels. Empty when no lasso 177 // is in progress or staged. 178 lassoPoints: [], 179 lassoActive: false, 180 181 // In-editor copy/paste â separate from the OS clipboard so we can 182 // round-trip layer alpha and metadata losslessly. 183 internalClipboard: null, 184 185 // ââ Editor DOM refs ââ 186 // Root container that openEditor mounts into. 187 container: null, 188 // Main image canvas + its 2D context. Re-created on every openEditor 189 // so the editor can reopen with fresh dimensions. 190 mainCanvas: null, 191 mainCtx: null, 192 193 // ââ Document + layers ââ 194 layers: [], 195 activeLayerId: null, 196 // Active tool ID â one of move/crop/transform/brush/eraser/clone/ 197 // lasso/wand/inpaint/rembg/harmonize/sharpen/upscale/style. 198 tool: 'move', 199 // Display zoom (1 = 100%). pan{X,Y} translate the canvas inside the 200 // viewport. 201 zoom: 1, 202 panX: 0, 203 panY: 0, 204 // Document dimensions in canvas pixels. 205 imgWidth: 0, 206 imgHeight: 0, 207 // Gallery image id this editor session is editing, or null for 208 // blank-canvas drafts. 209 imageId: null, 210 // Original file extension so save-over-original re-encodes in the 211 // same format (JPEG vs PNG matters: JPEG cuts upload size 5-10Ã for 212 // camera photos over remote tunnels). 213 originalExt: 'png', 214 // True between openEditor / closeEditor â guards async callbacks 215 // that fire after the user closes the editor (don't draw onto a 216 // dead canvas, don't re-mount the spinner). 217 editorOpen: false, 218 // Document-level click-away handlers registered for the current 219 // session. Tracked so closeEditor can detach them all cleanly. 220 // Mutated in place (push / length = 0); the reference never changes. 221 editorDocClickHandlers: [], 222 223 // ââ Undo / redo ââ 224 undoStack: [], 225 redoStack: [], 226 227 // ââ Layer offsets + id allocation ââ 228 // Map<layerId, {x, y}> â kept in a Map so we can serialise it 229 // separately from the layer's own canvas. Mutated in place. 230 layerOffsets: new Map(), 231 nextLayerId: 1, 232 233 // ââ Popup / panel handles ââ 234 fxPopupEl: null, 235 fxPopupLayerId: null, 236 fxMenuEl: null, 237 adjPopupEl: null, 238 // rAF-throttled live preview while sliders are dragged in adj popups. 239 adjRafPending: false, 240 historyPanelEl: null, 241 // Custom brush-cursor overlay element (circle following the mouse). 242 cursorEl: null, 243 // Hover-preview thumbnail floating element (singleton, repositioned). 244 layerThumbEl: null, 245 // Loading-overlay element (whirlpool + label). 246 editorLoadingEl: null, 247 248 // ââ Draft persistence ââ 249 draftId: null, 250 draftName: '', 251 persistTimer: null, 252 // Current PUT/POST promise so concurrent saves can chain. 253 persistInFlight: null, 254 // True when an edit happened during an in-flight save â triggers a 255 // follow-up persist after the current one finishes. 256 persistDirty: false, 257};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.