diff --git a/src/components/ContentEditor/ContentEditor.module.css b/src/components/ContentEditor/ContentEditor.module.css index 2d15c010..c38a0f63 100644 --- a/src/components/ContentEditor/ContentEditor.module.css +++ b/src/components/ContentEditor/ContentEditor.module.css @@ -27,7 +27,7 @@ .BackgroundMenu { z-index: 3; position: absolute; - right: 8em; + right: 19em; bottom: 3em; } diff --git a/src/components/ContentEditor/ContentEditor.tsx b/src/components/ContentEditor/ContentEditor.tsx index 5bc985c0..837672a4 100644 --- a/src/components/ContentEditor/ContentEditor.tsx +++ b/src/components/ContentEditor/ContentEditor.tsx @@ -2,7 +2,7 @@ import { render } from '@testing-library/react'; import { createRef, useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import { AppReducerState } from '../../reducers/AppReducer'; -import { IMG_URI, loadImage, obscureOverlay, renderImage, setupOverlayCanvas, selectOverlay, storeOverlay, clearOverlaySelection, getCanvas, initOverlay} from '../../utils/drawing'; +import { IMG_URI, loadImage, obscureOverlay, renderImage, setupOverlayCanvas, selectOverlay, storeOverlay, clearOverlaySelection, getCanvas, initOverlay, revealOverlay} from '../../utils/drawing'; import { MouseStateMachine } from '../../utils/mousestatemachine'; import { setCallback } from '../../utils/statemachine'; import styles from './ContentEditor.module.css'; @@ -40,6 +40,21 @@ const ContentEditor = () => { }, 'image/png', 1); } + const reveal = (x1: number, y1: number, x2: number, y2: number) => { + let overlayStuff = getCanvas(overlayCanvasRef, true); + if (!overlayStuff) return; + let { cnvs, ctx } = overlayStuff; + + revealOverlay.bind(ctx)(x1, y1, x2, y2); + overlayCanvasRef.current?.toBlob((blob: Blob | null) => { + if (!blob) { + // TODO SIGNAL ERROR + return; + } + dispatch({type: 'content/overlay', payload: blob}) + }, 'image/png', 1); + } + const keyPress = (key: string) => { if (key.toLowerCase() == 'enter') { let url: URL | null= null; @@ -107,7 +122,11 @@ const ContentEditor = () => { setCallback(sm, 'obscure', () => { obscure(sm.x1(), sm.y1(), sm.x2(), sm.y2()); sm.transition('wait'); - }) + }); + setCallback(sm, 'reveal', () => { + reveal(sm.x1(), sm.y1(), sm.x2(), sm.y2()); + sm.transition('wait'); + }); sm.setMoveCallback(selectOverlay.bind(overlayCtx)); sm.setStartCallback(storeOverlay.bind(overlayCtx)); setCallback(sm, 'push', () => dispatch({type: 'content/push'})); @@ -203,7 +222,9 @@ const ContentEditor = () => { - + diff --git a/src/utils/drawing.ts b/src/utils/drawing.ts index 948e88f9..e216834f 100644 --- a/src/utils/drawing.ts +++ b/src/utils/drawing.ts @@ -14,9 +14,9 @@ export function loadImage(uri: string): Promise { const img = new Image(); return new Promise((resolve, reject) => { img.onload = function() { resolve(this as HTMLImageElement); } - img.onerror = function() { reject('Image load failed'); } - img.src = uri; - // TODO MICAH get rid of this. This is a hack to stop an exception: + img.onerror = function(error) { reject(error); } + // Anonymous only works if the server cors are setup... Setting it avoids the + // error: // // The canvas has been tainted by cross-origin data. // @@ -25,7 +25,8 @@ export function loadImage(uri: string): Promise { // originates from the fact that our frontend in dev is on localhost:4200 and // I don't think cross-origin is setup properly for static data on the nose // server - // img.crossOrigin = 'Anonymous'; + img.crossOrigin = 'Anonymous'; + img.src = uri; }); } /*export function loadImage(data: Blob): Promise; @@ -102,6 +103,14 @@ export function obscureOverlay(this: CanvasRenderingContext2D, x1: number, y1: n baseData = this.getImageData(0, 0, this.canvas.width, this.canvas.height); } +export function revealOverlay(this: CanvasRenderingContext2D, x1: number, y1: number, x2: number, y2: number) { + if (baseData === null) return; + this.putImageData(baseData, 0, 0); + this.clearRect(x1,y1,x2-x1,y2-y1); + baseData = this.getImageData(0, 0, this.canvas.width, this.canvas.height); +} + + /** * Store off the default overlay image data. When using this method, you must * bind the context to it because "this" is expected to be a 2D context. diff --git a/src/utils/mousestatemachine.ts b/src/utils/mousestatemachine.ts index a38b66e5..20bb9c1e 100644 --- a/src/utils/mousestatemachine.ts +++ b/src/utils/mousestatemachine.ts @@ -32,11 +32,15 @@ export class MouseStateMachine implements StateMachine { 'complete': { // done recording - box selected 'down': 'record_mouse', 'obscure': 'obscure', + 'reveal': 'reveal', 'background': 'background_select', }, 'obscure': { 'wait': 'wait', }, + 'reveal': { + 'wait': 'wait', + }, 'background_select': { 'link': 'background_link', 'upload': 'background_upload',