/* * ModCanvastools */ import React, { useState, useEffect } from 'react'; import { useSelector, shallowEqual } from 'react-redux'; import { t } from 'ttag'; import useInterval from './hooks/interval'; import { getToday, dateToString, coordsFromString } from '../core/utils'; import { shardOrigin } from '../store/actions/fetch'; const keptState = { coords: '', tlcoords: '', brcoords: '', tlrcoords: '', brrcoords: '', tlccoords: '', brccoords: '', }; async function submitImageAction( action, canvas, coords, callback, ) { const data = new FormData(); const fileSel = document.getElementById('imgfile'); const file = (!fileSel.files || !fileSel.files[0]) ? null : fileSel.files[0]; data.append('imageaction', action); data.append('image', file); data.append('canvasid', canvas); data.append('coords', coords); const resp = await fetch(`${shardOrigin}/api/modtools`, { credentials: 'include', method: 'POST', body: data, }); callback(await resp.text()); } async function submitProtAction( action, canvas, tlcoords, brcoords, callback, ) { const data = new FormData(); data.append('protaction', action); data.append('canvasid', canvas); data.append('ulcoor', tlcoords); data.append('brcoor', brcoords); const resp = await fetch(`${shardOrigin}/api/modtools`, { credentials: 'include', method: 'POST', body: data, }); callback(await resp.text()); } async function submitRollback( date, canvas, tlcoords, brcoords, callback, ) { const data = new FormData(); const timeString = dateToString(date); data.append('rollback', timeString); data.append('canvasid', canvas); data.append('ulcoor', tlcoords); data.append('brcoor', brcoords); const resp = await fetch(`${shardOrigin}/api/modtools`, { credentials: 'include', method: 'POST', body: data, }); callback(await resp.text()); } async function submitCanvasCleaner( action, canvas, tlcoords, brcoords, callback, ) { const data = new FormData(); data.append('cleaneraction', action); data.append('canvasid', canvas); data.append('ulcoor', tlcoords); data.append('brcoor', brcoords); const resp = await fetch(`${shardOrigin}/api/modtools`, { credentials: 'include', method: 'POST', body: data, }); callback(await resp.text()); } async function getCleanerStats( callback, ) { const data = new FormData(); data.append('cleanerstat', true); const resp = await fetch(`${shardOrigin}/api/modtools`, { credentials: 'include', method: 'POST', body: data, }); if (resp.ok) { callback(await resp.json()); } else { callback({ }); } } async function getCleanerCancel( callback, ) { const data = new FormData(); data.append('cleanercancel', true); const resp = await fetch(`${shardOrigin}/api/modtools`, { credentials: 'include', method: 'POST', body: data, }); if (resp.ok) { callback(await resp.text()); } else { callback(''); } } function ModCanvastools() { const maxDate = getToday(); const [selectedCanvas, selectCanvas] = useState(0); const [imageAction, selectImageAction] = useState('build'); const [cleanAction, selectCleanAction] = useState('spare'); const [protAction, selectProtAction] = useState('protect'); const [date, selectDate] = useState(maxDate); const [resp, setResp] = useState(null); const [cleanerstats, setCleanerStats] = useState({}); const [submitting, setSubmitting] = useState(false); const [ canvasId, canvases, ] = useSelector((state) => [ state.canvas.canvasId, state.canvas.canvases, ], shallowEqual); useEffect(() => { selectCanvas(canvasId); }, [canvasId]); let descAction; switch (imageAction) { case 'build': descAction = t`Build image on canvas.`; break; case 'protect': descAction = t`Build image and set it to protected.`; break; case 'wipe': descAction = t`Build image, but reset cooldown to unset-pixel cd.`; break; default: // nothing } let descCleanAction; switch (cleanAction) { case 'spare': // eslint-disable-next-line max-len descCleanAction = t`Clean spare pixels that are surrounded by unset pixels`; break; case 'spareext': // eslint-disable-next-line max-len descCleanAction = t`Clean spare pixels that are surrounded by unset pixels and up to 1 other set pixels`; break; case 'spareextu': // eslint-disable-next-line max-len descCleanAction = t`Clean spare pixels that are surrounded by a single other color or unset pixels (VERY AGGRESSIVE ON CANVASES THAT ALLOW UNSET PIXELS (where there are two cooldowns)!)`; break; case 'makenull': // eslint-disable-next-line max-len descCleanAction = t`Turn every pixel in area to 0 (YOU REALLY SHOULDN'T DO THAT ON ANY AREA THAT ISN'T ALREADY MOSTLY 0)`; break; default: // nothing } useInterval(() => { getCleanerStats((stats) => setCleanerStats(stats)); }, 10000); const cleanerStatusString = (!cleanerstats.running) ? t`Status: Not running` // eslint-disable-next-line max-len : `Status: ${cleanerstats.method} from ${cleanerstats.tl} to ${cleanerstats.br} on canvas ${canvases[cleanerstats.canvasId].ident} to ${cleanerstats.percent} done`; return (
{resp && (
{resp.split('\n').map((line) => (

{line}

))} setResp(null)} > {t`Close`}
)}

{t`Choose Canvas`}: 

{t`Image Upload`}

{t`Upload images to canvas`}

{t`File`}: 

{descAction}

{t`Coordinates:`}  { let co = evt.target.value.trim(); co = coordsFromString(co); if (co) { co = co.join('_'); evt.target.value = co; } keptState.coords = co; }} />


{t`Pixel Protection`}

{ // eslint-disable-next-line max-len t`Set protection of areas (if you need finer grained control, use protect with image upload and alpha layers)` }

{t`Top-left corner`}:  { let co = evt.target.value.trim(); co = coordsFromString(co); if (co) { co = co.join('_'); evt.target.value = co; } keptState.tlcoords = co; }} />

{t`Bottom-right corner`}:  { let co = evt.target.value.trim(); co = coordsFromString(co); if (co) { co = co.join('_'); evt.target.value = co; } keptState.brcoords = co; }} />

{(window.ssv && window.ssv.backupurl) && (

{t`Rollback to Date`}

{t`Rollback an area of the canvas to a set date (00:00 UTC)`}

{ selectDate(evt.target.value); }} />

{t`Top-left corner`}:  { let co = evt.target.value.trim(); co = coordsFromString(co); if (co) { co = co.join('_'); evt.target.value = co; } keptState.tlrcoords = co; }} />

{t`Bottom-right corner`}:  { let co = evt.target.value.trim(); co = coordsFromString(co); if (co) { co = co.join('_'); evt.target.value = co; } keptState.brrcoords = co; }} />

)}

{t`Canvas Cleaner`}

{t`Apply a filter to clean trash in large canvas areas.`}

{descCleanAction}

{cleanerStatusString}

{t`Top-left corner`}:  { let co = evt.target.value.trim(); co = coordsFromString(co); if (co) { co = co.join('_'); evt.target.value = co; } keptState.tlccoords = co; }} />

{t`Bottom-right corner`}:  { let co = evt.target.value.trim(); co = coordsFromString(co); if (co) { co = co.join('_'); evt.target.value = co; } keptState.brccoords = co; }} />

); } export default React.memo(ModCanvastools);